How to Stop C/C++ WINAPI Window Showing on all Desktops? - c++

I am writing a C/C++ windows app which calls CreateWindow as follows:
HWND hWnd = CreateWindow(pszClassName, title_.c_str(), WS_OVERLAPPED | WS_VISIBLE | WS_POPUP | WS_SIZEBOX, 50, 50, 400, 100, NULL, NULL, hInst, this);
Nothing particularly complex about it, however, it is appearing on every desktop on my computer when I switch from one desktop to another with CTRL-WIN < or >.
How do you make window you create in an app remain only on the desktop that you created it on?
I am compiling this app in 64bit and running it on Windows 10.

Code:
Global:
WNDCLASSEX wc;
Window procedure:
case WM_KEYDOWN:
if(wParam == VK_F11)
{
wc.style = HWND_DESKTOP;//The window is child
//of desktop
}
break;
WinMain:
LPCSTR windowName = "Answer on StackOwerflow";
MSG messages;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "The classname";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
wc.lpszClassName,
windowName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
ShowWindow(hWnd);
UpdateWindow(hWnd);
while(GetMessage(&messages, NULL, 0, 0) > 0)
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return 0;

Related

Window redraw breaks after a few seconds

I have a main HWND with several child HWNDs. When I start the code the windows all draw properly and show up as they should, I can even move the main window around which essentially invokes InvalidateRect() calls which call a redraw of the main and child windows. However, after about two seconds, all of this functionality stops and upon moving the window the main window draw ends up drawing all of the child windows at the size of the main window. Note that this problem occurs with any redrawing of the main window. This is quite strange, and I am inclined to think that the problem lies with my HWND setup and not the OpenGL integration as both my GL child window and the other HWND child windows are subject to the issue.
Here is my main window creation:
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) {
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(wcex.hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = CreateSolidBrush(RGB(7, 7, 8));
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
//MessageBox(NULL, _T("This message box is completely unnecessary and is designed to annoy you."), _T("Annoyance"), NULL);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
HWND hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1600, 900, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindowEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
Here is the main window procedure:
LRESULT CALLBACK WndProc(_In_ HWND hWnd, _In_ UINT message, _In_ WPARAM wParam, _In_ LPARAM lParam) {
//a = std::make_tuple<float, float, float>(1.0f, 0.0f, 0.0f);
PAINTSTRUCT ps;
HDC hdc = GetDC(hWnd);
TCHAR greeting[] = _T("Data Grapher for Paper");
RECT rcClient;
WNDCLASSEXW wcex1;
wcex1.cbSize = sizeof(WNDCLASSEX);
wcex1.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex1.lpfnWndProc = (WNDPROC)GLProc;
wcex1.cbClsExtra = 0;
wcex1.cbWndExtra = 0;
wcex1.hInstance = glInstance;
wcex1.hIcon = LoadIcon(wcex1.hInstance, IDI_APPLICATION);
wcex1.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex1.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
wcex1.lpszMenuName = nullptr;
wcex1.lpszClassName = _T("GLClass");
wcex1.hIconSm = LoadIcon(wcex1.hInstance, IDI_APPLICATION);
RegisterClassExW(&wcex1);
WNDCLASSEXW dataViewClass;
dataViewClass.cbSize = sizeof(WNDCLASSEX);
dataViewClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
dataViewClass.lpfnWndProc = (WNDPROC)DataProc;
dataViewClass.cbClsExtra = 0;
dataViewClass.cbWndExtra = 0;
dataViewClass.hInstance = hInst;
dataViewClass.hIcon = LoadIcon(dataViewClass.hInstance, IDI_APPLICATION);
dataViewClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
dataViewClass.hbrBackground = CreateSolidBrush(RGB(27, 27, 28));
dataViewClass.lpszMenuName = nullptr;
dataViewClass.lpszClassName = _T("DataClass");
dataViewClass.hIconSm = LoadIcon(dataViewClass.hInstance, IDI_APPLICATION);
RegisterClassExW(&dataViewClass);
WNDCLASSEXW dataTextClass;
dataTextClass.cbSize = sizeof(WNDCLASSEX);
dataTextClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
dataTextClass.lpfnWndProc = (WNDPROC)dataTextProc;
dataTextClass.cbClsExtra = 0;
dataTextClass.cbWndExtra = 0;
dataTextClass.hInstance = hInst;
dataTextClass.hIcon = LoadIcon(dataTextClass.hInstance, IDI_APPLICATION);
dataTextClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
dataTextClass.hbrBackground = CreateSolidBrush(RGB(27, 27, 28));
dataTextClass.lpszMenuName = nullptr;
dataTextClass.lpszClassName = _T("dataTextClass");
dataTextClass.hIconSm = LoadIcon(dataTextClass.hInstance, IDI_APPLICATION);
RegisterClassExW(&dataTextClass);
WNDCLASSEXW quitButtonClass;
quitButtonClass.cbSize = sizeof(WNDCLASSEX);
quitButtonClass.style = BS_OWNERDRAW;//CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
quitButtonClass.lpfnWndProc = (WNDPROC)quitButtonProc;
quitButtonClass.cbClsExtra = 0;
quitButtonClass.cbWndExtra = 0;
quitButtonClass.hInstance = hInst;
quitButtonClass.hIcon = LoadIcon(quitButtonClass.hInstance, IDI_APPLICATION);
quitButtonClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
quitButtonClass.hbrBackground = CreateSolidBrush(RGB(27, 27, 28));
quitButtonClass.lpszMenuName = nullptr;
quitButtonClass.lpszClassName = _T("quitButtonClass");
quitButtonClass.hIconSm = LoadIcon(quitButtonClass.hInstance, IDI_APPLICATION);
RegisterClassExW(&quitButtonClass);
WNDCLASSEXW saveImageButtonClass;
saveImageButtonClass.cbSize = sizeof(WNDCLASSEX);
saveImageButtonClass.style = BS_OWNERDRAW;//CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
saveImageButtonClass.lpfnWndProc = (WNDPROC)saveImageButtonProc;
saveImageButtonClass.cbClsExtra = 0;
saveImageButtonClass.cbWndExtra = 0;
saveImageButtonClass.hInstance = hInst;
saveImageButtonClass.hIcon = LoadIcon(saveImageButtonClass.hInstance, IDI_APPLICATION);
saveImageButtonClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
saveImageButtonClass.hbrBackground = CreateSolidBrush(RGB(27, 27, 28));
saveImageButtonClass.lpszMenuName = nullptr;
saveImageButtonClass.lpszClassName = _T("saveImageButtonClass");
saveImageButtonClass.hIconSm = LoadIcon(saveImageButtonClass.hInstance, IDI_APPLICATION);
RegisterClassExW(&saveImageButtonClass);
WNDCLASSEXW switchModeButtonClass;
switchModeButtonClass.cbSize = sizeof(WNDCLASSEX);
switchModeButtonClass.style = BS_OWNERDRAW;//CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
switchModeButtonClass.lpfnWndProc = (WNDPROC)switchModeButtonProc;
switchModeButtonClass.cbClsExtra = 0;
switchModeButtonClass.cbWndExtra = 0;
switchModeButtonClass.hInstance = hInst;
switchModeButtonClass.hIcon = LoadIcon(switchModeButtonClass.hInstance, IDI_APPLICATION);
switchModeButtonClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
switchModeButtonClass.hbrBackground = CreateSolidBrush(RGB(27, 27, 28));
switchModeButtonClass.lpszMenuName = nullptr;
switchModeButtonClass.lpszClassName = _T("switchModeButtonClass");
switchModeButtonClass.hIconSm = LoadIcon(switchModeButtonClass.hInstance, IDI_APPLICATION);
RegisterClassExW(&switchModeButtonClass);
switch (message)
{
case WM_PAINT:
/*
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, Windows desktop!"
// in the top left corner.
//doGL(hdc);
TextOut(hdc, 5, 5, greeting, _tcslen(greeting));
// End application-specific layout section.
EndPaint(hWnd, &ps);
ReleaseDC(hWnd, hdc);
*/
break;
case WM_CREATE:
{
InitCommonControls();
CreateWindowEx(WS_EX_APPWINDOW, _T("quitButtonClass"), _T("Quit"), WS_CHILD, 20, 50, 100, 25, hWnd, (HMENU)1, hInst, NULL);
CreateWindowEx(WS_EX_APPWINDOW, _T("saveImageButtonClass"), _T("Save Image"), WS_CHILD, 140, 50, 80, 25, hWnd, (HMENU)2, hInst, NULL);
CreateWindowEx(WS_EX_APPWINDOW, _T("switchModeButtonClass"), _T("Toggle Clock"), WS_CHILD, 20, 90, 100, 25, hWnd, (HMENU)3, hInst, NULL);
w = CreateWindowEx(WS_EX_APPWINDOW, _T("GLClass"), _T("GL"), WS_CHILD, 0, 0, 160, 90, hWnd, (HMENU)4, hInst, NULL);
HDC dc = GetDC(w);
HGLRC rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
//glfwInit();
int argc = 1;
char* argv[1] = { (char*)"Something" };
glutInit(&argc, argv);
glewInit();
initializeText();
imageSaveQueued = false;
graphScale = .8f;
HWND da = CreateWindowEx(WS_EX_APPWINDOW, _T("DataClass"), _T("Data"), WS_CHILD, 0, 0, 160, 90, hWnd, (HMENU)5, hInst, NULL);
//makes it so the data field accepts files
DragAcceptFiles(da, TRUE);
//set the data mode to by bz graph by default
mode = 1;
//dataList = CreateWindow(WC_LISTVIEW, TEXT("Load Data"), WS_CHILD | LVS_REPORT | LVS_EDITLABELS, 300, 700, 500, 100, hWnd, (HMENU)6, hInst, NULL);
//dataText = CreateWindowEx(WS_EX_APPWINDOW, _T("dataTextClass"), _T("dataText"), WS_CHILD, 200, 200, 200, 200, hWnd, (HMENU)7, hInst, NULL);
//createListColumn(dataList, 1, L"Year", 0);
//createListItem(dataList, _T("Thing"), 0);
//SendMessage(dataList, LB_ADDSTRING, NULL, (LPARAM)"words");
//CreateWindow(TEXT("button"), TEXT("Save Graph"), WS_VISIBLE | WS_CHILD, 140, 90, 100, 25, hWnd, (HMENU)7, NULL, NULL);
//trackA = CreateWindowEx(0, TRACKBAR_CLASS, _T("Start"), WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS | TBS_ENABLESELRANGE, 900, 700, 200, 30, hWnd, (HMENU)8, hInst, NULL);
//trackB = CreateWindowEx(0, TRACKBAR_CLASS, _T("End"), WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS | TBS_ENABLESELRANGE, 900, 730, 200, 30, hWnd, (HMENU)8, hInst, NULL);
//SendMessage(trackA, TBM_SETRANGE,
//(WPARAM)TRUE, // redraw flag
//(LPARAM)MAKELONG(0, 100));
GetClientRect(hWnd, &rcClient);
EnumChildWindows(hWnd, EnumChildProc, (LPARAM)&rcClient);
break;
}
case WM_COMMAND:
{
/*
if (LOWORD(wParam) == 2) {
PostQuitMessage(0);
}
*/
if (LOWORD(wParam) == 7) {
smoothLine = !smoothLine;
InvalidateRect(w, NULL, TRUE);
}
break;
}
case WM_DESTROY:
FreeLibrary(comctllib);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
I'm reluctant to paste more code here in the initial question as there is quite a lot more code, but if there is something more needed (including screenshots) I am happy to add it.

The window I created in C++ is not displayed

I tried to create a window in an Empty C++ Project in Visual Studio, but when I run it, it shows me no window. However, it doesn't give me any error too.
#include <Windows.h>
using namespace std;
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
const auto pClassName = "TextClass";
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(wc);
wc.style = CS_OWNDC;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = nullptr;
wc.hCursor = nullptr;
wc.hbrBackground = nullptr;
wc.lpszMenuName = pClassName;
wc.hIconSm = nullptr;
RegisterClassEx(&wc);
HWND hWnd = CreateWindowEx(
0,
pClassName,
"A sad Window",
WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
200, 200, 640, 480,
nullptr, nullptr, hInstance, nullptr);
ShowWindow(hWnd, SW_SHOW);
while (true);
return 0;
}
You have a typo: you are setting
wc.lpszMenuName = pClassName;
instead of wc.lpszClassName.
I believe just fixing that will get the window on the screen but the executable will then hang with it on the screen because nothing is fielding messages.
A minimal message loop instead of
while (true) ...
would be
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) > 0 )
DispatchMessage( &msg );

Create Child window on windows API

I'm trying to add a child window to my main window, but the function CreatWindow is throwing an exception saying that can't access address at 0x00000, but it works fine when I try to create a button, I tracked the variables and none of them are null, here it is:
WNDCLASSEX windowClass;
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.hInstance = hInstance;
windowClass.lpfnWndProc = NULL;
windowClass.lpszClassName = className;
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.lpszMenuName = NULL;
if (!RegisterClassEx(&windowClass)){
return;
}
window = CreateWindowEx(0,
className,
(LPCTSTR)NULL,
WS_CHILD | WS_BORDER,
0, 0, 0, 0,
owner,
(HMENU)ID,
hInstance,
NULL);
the code above giving the error, the important variables come from here:
gl = new OpenGLContainer("hellogl", hInstance);
addChild(gl);
the first parameter is the className, the constructor only performs an attribution, the addChild method call gl->setOwner(window_handler) and gl->create() which is the first piece of code I posted.
I also saw the stack list, and the problem is after the program enter in the CreateWindow function, which is very strange because the debugger shows that none of the values(pointers) are null.
Could it be failing because lpfnWndProc is NULL?

WinAPI: Create a window with a specified client area size

I was wondering how can I create a window using Win32 API with a specific client area size.
When trying to create a window using the following piece of code, the entire window is 640x480, with the window's chrome taking some of the client area:
HWND hWnd;
WNDCLASSEX WndClsEx;
ZeroMemory(&WndClsEx, sizeof(WNDCLASSEX));
WndClsEx.cbSize = sizeof(WNDCLASSEX);
WndClsEx.style = CS_HREDRAW | CS_VREDRAW;
WndClsEx.lpfnWndProc = DefWindowProc;
WndClsEx.cbClsExtra = 0;
WndClsEx.cbWndExtra = 0;
WndClsEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndClsEx.lpszMenuName = NULL;
WndClsEx.lpszClassName = TEXT("Title");
WndClsEx.hInstance = hInstance;
WndClsEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&WndClsEx);
hWnd = CreateWindowEx( NULL,
TEXT("Title"),
TEXT("Title"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);
Assuming simple math won't quite solve the problem, how do I take the chrome size into account?
Note: I'm using SDL after creating the window, but I'm guessing it's bound to the window size and makes no difference to its size.
You can use the AdjustWindowRect or AdjustWindowRectEx function to calculate the window size given a desired client area size.

No icon in title bar after switching from WNDCLASS to WNDCLASSEX

I just switched the game to use WNDCLASSEX so I can change the hIconSm, but for some reason there isn't an icon in the title bar anymore. The cursor and icon on the task bar and the icon for the EXE are all working fine though. Here is the main part of the window creation code:
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WinProc;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_ERROR);
wc.hIconSm = LoadIcon(NULL, IDI_ASTERISK);
wc.hCursor = LoadCursorFromFile((LPCSTR)"FierceCursor.cur");
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
wc.lpszClassName = "FierceWindow";
RegisterClassEx(&wc);
game->hinstance = hInstance;
hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,
"FierceWindow", "Fierce",
WS_OVERLAPPED, 400, 100,
game->SCREEN_WIDTH, game->SCREEN_HEIGHT,
NULL, NULL, hInstance, NULL);
I've tried a few different settings for CreateWindowEx in hopes that maybe I used a style without an icon, but no luck. I'm using default icons right now to test.
Won't compile:
error: cast from 'CHAR*' to 'WORD' loses precision
Thanks for the edit btw.
Edit - Got it to compile by changing it to:
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(32513));
wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(32513));
It's because of your window style. The icon appears only if you add WS_SYSMENU style.
WS_OVERLAPPED|WS_SYSMENU