Questions on first Win32 windows application

Started by
4 comments, last by Fredericvo 9 years, 6 months ago

I learning how to program win32 applications, and starting with the "Hello World" version found on the MSDN:

http://msdn.microsoft.com/en-us/library/bb384843.aspx

I have some questions based on their code:

1. They have their windows class name as


static TCHAR szWindowClass[] = _T("win32app");

Why would you make it a TCHAR instead of something like:


const char szWindowClass[]  = "win32app";

I have also seen:


wchar_t szWindowClass[] = L"win32app";

This prefix L and _T is confusing to me. Why would you use one of these methods over the other? In modern c++ programming which is the 'best' one to use?

2. They have this line of code in the full code:


hInst = hInstance; // Store instance handle in our global variable

I noticed you can comment it out and it does not affect the program. In fact, they do not use hInst after this is written, so what is its purpose?

3. They have this line:


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

but I have also seen the same sort of line written as WinProc instead of WndProc. I cant find much information on WinProc. What is the difference?

4. In their callback they have this code:


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    TCHAR greeting[] = _T("Hello, World!");

    switch (message)
    {
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        TextOut(hdc, 5, 5, greeting, _tcslen(greeting));
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
        break;
    }

    return 0;
}

I am confused as to a few things.

- The program itself just writes "Hello World", but how does it know which "case" to take.

- In this particular program there is no input you can do except close or minimize the window, so as the program is running, what is exactly the default value of "message"?

- Does clicking on the red X mean that case "WM_DESTORY" has been selected?

5. I was playing around with some of the code to change the background color and altered this line:


wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

. I changed COLOR_WINDOW + 1 to COLOR_WINDOW + 240. In this case the window does not show and the call "Call to RegisterClassEx failed!" pops up. I ran the code a few times and then changed it back to + 1. When you save it and run it you get an error from VS2013 saying:

"cannot open HelloWorldApp.exe for writing", and when I check task manager I can see a couple of "HelloWorldApp.exe" sitting there. You need to end task them all to make the program compile again. So I guess the code does not properly handle a failed run apart from the message box.

  • In this case how would you properly shut the program down and release the memory?

Thank you for your time.

Advertisement

1. That stems from their confused sense of Unicode and a wrong thinking of needing to keep compatibility with ASCII.

Read http://utf8everywhere.org/ on how to better handle this!

2. Sometimes its needed as a function parameter, but there is also another function to retrieve it if you dont have it.

3. Its a callback you provide, only the function address matters and you can choose any name you like for it. Under some circumstances it may be even useful to have more than one.

4. There are a countless number of messages that get put into a queue, which you there retrieve with GetMessage and pass along to Dispatchmessage, which internally calls your callback function. When clicking the x all kinds of mouse messages get through first and then when the click is confirmed you get a WM_CLOSE, to which the typical response is calling DestroyWindow, which sends the WM_DESTROY and there you call PostQuitMessage, which sends WM_QUIT, which should make your message loop exit from a special return value from GetMessage. Its all pretty complicated and thats why most messages you are not interested in are forwarded to DefWindowProc, which is like your window procedure, but premade for default handling.

5. You cant just add a magic number to a (hidden) pointer and expect the program to still work. Read up on what alternative values you can provide to change it.

Thank you wintertime, may I please have clarification on the following things:


3. Its a callback you provide, only the function address matters and you can choose any name you like for it. Under some circumstances it may be even useful to have more than one.

What I was actually referring to was the WndProc() function. In some win32 examples I have seen WinProc() written instead, and cannot understand the difference between these two functions.


5. You cant just add a magic number to a (hidden) pointer and expect the program to still work. Read up on what alternative values you can provide to change it.

In this case, I was just mucking around to see what that option did. But what I was trying to ask, is in the case that the RegisterClassE() fails (such as it did when I entered an invalid number), how is one supposed to make sure the program shuts down correctly and does not sit in task manager?

Thanks again for your time and knowledge.

In the WNDCLASSEX structure, there's a parameter called lpfnWndProc. This simply tells windows the name of your window procedure, and must match the corresponding LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam).

There's nothing to stop you from using:

wcex.lpfnWndProc = iLikeEatingChocolateIcreCream;

.....

LRESULT CALLBACK iLikeEatingChocolateIcreCream(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

......

}

But obviously that doean't make much sense. So, by tradition, the window procedure is normally called WndProc/WinProc,WindowProc etc.

Ohhhhh.. thanks.. for some reason I thought it was a built in windows function, I forgot they declared it as that name in the function prototype.

Thanks for clearing that up

You asked many questions at once but in a nutshell the "weird" typedefs have to do with unicode support and the switch case dispatches different messages. You only process one message per callback. If I mouse over your app for example you'll get a lot of WM_MOUSEMOVE messages that you treat one per call of and manage appropriately. Unprocessed messages are processed by defwinproc.
Naming your callback WndProc or WinProc is entirely your own decision and subject to conventions.

This topic is closed to new replies.

Advertisement