Sign in to follow this  
CornyKorn21

Win32 Window Issue (C++)

Recommended Posts

I was wondering if anyone could help me out with a little problem I am having.

I started a new empty Windows C++ project in Visual Studio 2010. I added, what I've known to be, the basic code for getting a window up and running with a simple message loop. Already I am having an unusual issue with my window. When I launch the program my window appears but I always get the busy cursor icon. I have no control over minimizing/maximizing/moving/etc. the window. Has anyone ever seen this happen? I'm on Windows 7 if it makes any difference.

From what I can tell this looks no different than any other Windows program I have written...

One thing I tried was to use the basic Windows C++ project template instead of empty. That seemed to work well. The only thing they seemed to do different is use TranslateAccelerator, which I have never used before, instead of PeekMessage.

[code]
#include <Windows.h>

//Forward declarations
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND CreateAndRegisterWindow(const char* name);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
HWND hWnd = CreateAndRegisterWindow("Sandbox");
if(hWnd == NULL)
{
MessageBox(NULL, "Error!", "Unable to create and register the Sandbox window", MB_ICONERROR);
return -1;
}

MSG msg = { };
while(msg.message != WM_QUIT)
{
//Process current window messages
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
}
}

return static_cast<int>(msg.wParam);
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
}
return 0;

case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);

FillRect(hdc, &ps.rcPaint, reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1));
EndPaint(hWnd, &ps);
}
return 0;
}

return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

HWND CreateAndRegisterWindow(const char* name)
{
//Register the window class.
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = name;

RegisterClass(&wc);

//Create the window
HWND hWnd = CreateWindowEx(
0,
name,
name,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
NULL,
NULL);

if(hWnd == NULL)
{
return NULL;
}

ShowWindow(hWnd, SW_SHOWDEFAULT);
return hWnd;
}
[/code]

Share this post


Link to post
Share on other sites
[quote name='Endurion' timestamp='1307039681' post='4818789']
You need to set a valid class cursor in your WNDCLASS. If you set it to NULL (which you do) Windows displays the busy cursor.


The default is usually LoadCursor( NULL, IDC_ARROW );
[/quote]

Sorry, forgot to mention, I do have that set up in my current code base. I'm away from my main computer so I had to pull from my last commit to my repository. My WNDCLASS looks more like this:

[code]
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = name;
[/code]

Share this post


Link to post
Share on other sites
There is nothing wrong with your code above except the mentioned window class cursor thing. I compiled it and it works fine.

What exactly do you mean "I have no control over minimizing/maximizing/moving/etc. the window."? Maybe you're running a different maybe older version of the exe than the one whose code you posted?

Share this post


Link to post
Share on other sites
[quote name='Endurion' timestamp='1307039681' post='4818789']
You need to set a valid class cursor in your WNDCLASS. If you set it to NULL (which you do) Windows displays the busy cursor.
[/quote]

that is not correct, from personel experiance.
it uses the default windows arrow.

Share this post


Link to post
Share on other sites
[quote name='Amr0' timestamp='1307043866' post='4818812']
There is nothing wrong with your code above except the mentioned window class cursor thing. I compiled it and it works fine.

What exactly do you mean "I have no control over minimizing/maximizing/moving/etc. the window."? Maybe you're running a different maybe older version of the exe than the one whose code you posted?


[/quote]

What I mean is that I get the busy cursor (I'm on Windows 7 so the spinning doughnut). When I attempt to grab the title bar I can not move the window. When I try to press minimize or maximize nothing happens, and when I try to press the close icon nothing happens. Same thing when I attempt to grab the edge of the window in order to resize. Now I understand I may have turned off some of those features with my window setup, but I'm pretty sure I should at minimum be able to close the window and move it around by the title bar.

Edit: The code I have posted + the update to my WNDCLASS in the other post is currently what I am building and running.

Share this post


Link to post
Share on other sites
[quote name='ryan20fun' timestamp='1307044277' post='4818815']
[quote name='Endurion' timestamp='1307039681' post='4818789']
You need to set a valid class cursor in your WNDCLASS. If you set it to NULL (which you do) Windows displays the busy cursor.
[/quote]

that is not correct, from personel experiance.
it uses the default windows arrow.
[/quote]

No it doesn't. It doesn't display the busy cursor either. It simply doesn't change it.


If the cursor member of the window class is set to NULL, and the application doesn't take charge of setting the mouse cursor itself (for example, in the window's message processor procedure in response to WM_SETCURSOR), then the operating system will not set the cursor for you. What this means is the cursor will remain the same as it was before it entered the window's client area. That's why if you move the cursor to the outer frame of the window as if you want to resize it, then bring it back inside the client area, the cursor will still look like the "sizing" cursor. Note that the default window procedure handles setting the cursor when the mouse is in the non-client area.

In fact, the default window procedure's response to WM_SETCURSOR is to set the cursor to whatever it is that is assigned to the hCursor member of the window class structure.

Share this post


Link to post
Share on other sites
Are you running the EXE standalone? What happens if you attach a debugger and break execution? Where does it indicate that execution is halting, if anywhere specific?

It sounds suspiciously like your message pump is not working and/or your window procedure is not deferring to DefWindowProc() correctly; either of those two situations can lead to behaviour like what you describe, although there may well be other causes as well.

Strip your code down to a minimal example that reproduces the problem, and post it in its entirety; your code as described works fine for me on Win7 32-bit. If you're positive that there's no difference between the code you're compiling and what's posted here, and a full clean/rebuild of your EXE doesn't help, try just starting a new project from scratch. Could be that some compiler setting or option got borked and now something is screwy.

Share this post


Link to post
Share on other sites
[quote name='ApochPiQ' timestamp='1307046660' post='4818842']
Are you running the EXE standalone? What happens if you attach a debugger and break execution? Where does it indicate that execution is halting, if anywhere specific?

It sounds suspiciously like your message pump is not working and/or your window procedure is not deferring to DefWindowProc() correctly; either of those two situations can lead to behaviour like what you describe, although there may well be other causes as well.

Strip your code down to a minimal example that reproduces the problem, and post it in its entirety; your code as described works fine for me on Win7 32-bit. If you're positive that there's no difference between the code you're compiling and what's posted here, and a full clean/rebuild of your EXE doesn't help, try just starting a new project from scratch. Could be that some compiler setting or option got borked and now something is screwy.
[/quote]

I am running the EXE through my debugger, it doesn't indicate the execution is halting in any specific place. I threw in some rendering code at one point that rendered my FPS and MSPF and those all updated and rendered properly.

The current code I am compiling is what I posted.

I guess when I get home tonight I'll trash the project and try starting from scratch again. Thanks for your help.

Share this post


Link to post
Share on other sites
[quote name='Amr0' timestamp='1307046561' post='4818838']
[quote name='ryan20fun' timestamp='1307044277' post='4818815']
[quote name='Endurion' timestamp='1307039681' post='4818789']
You need to set a valid class cursor in your WNDCLASS. If you set it to NULL (which you do) Windows displays the busy cursor.
[/quote]

that is not correct, from personel experiance.
it uses the default windows arrow.
[/quote]

No it doesn't. It doesn't display the busy cursor either. It simply doesn't change it.


If the cursor member of the window class is set to NULL, and the application doesn't take charge of setting the mouse cursor itself (for example, in the window's message processor procedure in response to WM_SETCURSOR), then the operating system will not set the cursor for you. What this means is the cursor will remain the same as it was before it entered the window's client area. That's why if you move the cursor to the outer frame of the window as if you want to resize it, then bring it back inside the client area, the cursor will still look like the "sizing" cursor. Note that the default window procedure handles setting the cursor when the mouse is in the non-client area.

In fact, the default window procedure's response to WM_SETCURSOR is to set the cursor to whatever it is that is assigned to the hCursor member of the window class structure.


[/quote]

thants what i ment

Share this post


Link to post
Share on other sites
OK, so I figured I would give you guys an update. Since I was writing this post away from my dev machine I was 100% certain I had tried it as the code I posted. Apparently I was wrong, sorry about that. I should verify what I am doing before I claim I am doing it in the future.

I had left in code to initialize raw input. Apparently setting up a raw input device with RIDEV_NOLEGACY caused the issue I was having. As soon as I removed that flag when creating my raw input devices everything cleared up.

Share this post


Link to post
Share on other sites
If you want to stick to using raw win32 window handling, I would download WTL off sourceforge and use that, it takes care of a lot of the boilerplate stuff out of the box and is very customizable, and is pretty much straight to the metal as far as frameworks go (all templates, no virtual sillyness). Ideal for a simple game imo.

Otherwise a larger framework (Qt, wxWidgets, MFC) can be made to work but is a lot more work (though they have much better documentation & samples).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this