Win 32 help please

Pages: 12
Ok so im following this tutorial online and i got stuck, i keep getting this error.


C:\Users\Chay Hawk\Desktop\Win32\main.cpp|18|warning: 'typedef' was ignored in this declaration|
C:\Users\Chay Hawk\Desktop\Win32\main.cpp||In function 'int WinMain(HINSTANCE__*, HINSTANCE__*, CHAR*, int)':|
C:\Users\Chay Hawk\Desktop\Win32\main.cpp|32|error: invalid conversion from 'LRESULT (*)(HWND__*, UINT, WPARAM, LPARAM)' to 'LRESULT (*)(HWND__*, UINT, WPARAM, LPARAM)'|
C:\Users\Chay Hawk\Desktop\Win32\main.cpp|33|warning: no return statement in function returning non-void|
||=== Build finished: 1 errors, 2 warnings ===|


here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <windows.h>

typedef struct WndClassEx
{
    UINT       cbSize;
    UINT       style;
    WNDPROC    lpfnWndProc;
    int        cbClsExtra;
    int        cbWndExtra;
    HINSTANCE  hInstance;
    HICON      hIcon;
    HCURSOR    hCursor;
    HBRUSH     hbrBackground;
    LPCTSTR    lpszMenuName;
    LPCTSTR    lpszClassName;
    HICON      hIconSm;
};

LRESULT WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
                   int nCmdShow)
{
    WNDCLASSEX wndClsEx;

    wndClsEx.cbSize = sizeof(WNDCLASSEX);
    wndClsEx.cbClsExtra = 0;
    wndClsEx.cbWndExtra = 0;
    wndClsEx.hInstance = hInstance;
    wndClsEx.style = CS_HREDRAW | CS_VREDRAW;
    wndClsEx.lpfnWndProc = WndProcedure;
}

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
    case WM_DESTROY:
        PostQuitMessage(WM_QUIT);
        break;
    default:
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    return 0;
}


The code looks EXACTLY like it does in the tutorial so why does it keep giving me this error?
If the code is exactly like the tutorial, I'd throw it away/delete it.

1. WNDCLASSEX is defined in one of the Windows headers, so there's no need for WndClassEx

2. the typedef is missing the typedef name

typedef <what you're typedef-ing> name

here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct WndClassEx
{
    UINT       cbSize;
    UINT       style;
    WNDPROC    lpfnWndProc;
    int        cbClsExtra;
    int        cbWndExtra;
    HINSTANCE  hInstance;
    HICON      hIcon;
    HCURSOR    hCursor;
    HBRUSH     hbrBackground;
    LPCTSTR    lpszMenuName;
    LPCTSTR    lpszClassName;
    HICON      hIconSm;
} SOME_OR_OTHER_NAME; // this is missing 


3. The forward declaration of WndProcedure is missing the calling convention.

4. WinMain must return an integer value. Usually the message loop exit code

5. WinMain needs to register the class

6. WinMain needs to create the windows

7. WinMain need a message loop




Last edited on
So this code is shit in general and whoever wrot the tutorial is wrong?
Also in code blocks when i pick win32 app it gives me the option of dialog and frame based, what is the difference? I notice the code for dialog based is alot less complicated.
Well, the code you posted in majorly incomplete and has bugs...

When you use a dialog, Windows does some of the work for you. It uses a special window class (identifed by the atom #32770), which is provided by the system. This knows how to convert a dialog resource into a window with controls. It also know how to handle some of the standard windows messages leaving you to concentrate mostly on the handling of the control messages.
Last edited on
A repaired version of the code above, which just displays a blank window, is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#define WIN32_LEAN_AND_MEAN
// stops windows.h dragging is loads of unwanted stuff
#include <windows.h>

const char achTitle      [] = "Example #1";
const char achWindowClass[] = "ExampleNumberOne";

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
                   int nCmdShow)
{
    MyRegisterClass(hInstance);

    if(!InitInstance(hInstance, nCmdShow))
    {
        return FALSE;
    }

    MSG msg = {0};
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
    case WM_DESTROY:
        PostQuitMessage(WM_QUIT);
        break;
    default:
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    return 0;
}

ATOM
MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex = {0};

    wcex.cbSize        = sizeof(WNDCLASSEX);
    wcex.style         = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc   = WndProcedure;
    wcex.hInstance     = hInstance;
    wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszClassName = achWindowClass;

    return RegisterClassEx(&wcex);
}


BOOL
InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    HWND hWnd = CreateWindow(achWindowClass,
                             achTitle,
                             WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT,
                             0,
                             CW_USEDEFAULT,
                             0,
                             NULL,
                             NULL,
                             hInstance,
                             NULL);

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

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    return TRUE;
}


(the new bits were nicked from Visual C++ generated code and then simplified)
Last edited on
Yes, code blocks has pretty much the exact same thing when you start a frame based application. But what im most confused on are the words and how this stuff works. Im confused on HIWORD, LOWORD, UINT, APIENTRY, HINSTANCE, MAKEINTRESOURCE, DLGPROC, HWND. I tried learning this stuff a long time ago but it was just too complicated, but i am going to conquer it this time. I know that HIWORD takes the upper 16 bits of a value and LOWORD takes the lower 16 bits but, bits of what? I found this explanation on a forum

"Well the Win32 API uses bitpacking in the wParam and lParam to fit extra information about the message into the params passed to your WndProc. You extract this information using the HIWORD and LOWORD macros."

What is bit packing, what is win32 on a bit level? does it communicate in bits? I have tried looking this stuff up on the microsoft website and others but i keep getting the same technical jargon thats incomprehensible to me. Why do i need these words, why are they important and what do they actually do.

Also i heard a rumor that microsoft will replace Win32 with something better, is that true? Win32 seems kind of old to me for some reason, it just seems ancient.
Last edited on
Can anyone help me?
Tip:
Read what numbers representatioon are. Convert them to binary (base 2, or "bit level" in your words), decimal (base 10, this all humans use all the time) and hexadecimal (base 16, you see them also sometimes).

Try to see what, say, number 18 looks kike in base 2, base 10 and base 16 representation by yourself and you will take a great step to understand.
Im not sure what any of that means...
Well ch1156, your questions are a perfect example of why I think an aspiring C++ programmer should take a very hard and sincere look at the C programming language. Also, any of Charles Petzold's Win Api books (1995 through 1998 editions) would explain all these mysteries to you. Its how most folks learned this stuff.

Messages come fast and furious in Windows, so its of utmost importance that the low level details of how it functions be efficient. A 32 bit integer can be decomposed into 32 bits, or four 8 bit bytes, or 2 16 bit words. MS found that 16 bit words would be an efficient way of packaging two integral quantities within a single 32 bit double word variable. With 32 bit operating systems, fastest memory access occurs with 32 bit quantities. With 64 bit OS, it would be 64 bit BIG INTEGERS.

Anyway, HIWORD and LOWORD are macros that use a union I believe, to extract the 16 bit parts out of the 32 bit quantity.

Windows headers contain thousands of typedefs and macros that are used in Windows coding.

Please realize that for those of us who code this way, it took years to master this stuff. Asking questions is good.
Last edited on
No unions in sight! (Just boring shifts and stuff)

From windef.h

1
2
#define LOWORD(l)           ((WORD)(((DWORD_PTR)(l)) & 0xffff))
#define HIWORD(l)           ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff)) 
Last edited on
I do have Petzolds 5th edition book in PDF format and i was looking through it and i understood it alright, i guess i'll just read through it and see what i can come up with.
But doesnt he use C with it not C++? Idk i was learning and i made a simple message box, it was cool no big problem then i got to this one part where you make thre actual window and it discouraged me because there was A LOT of code for just a simple blank window.

No unions in sight! (Just boring shifts and stuff)


Right Andy. After I wrote that I got to thinking its just bit shifts.

Yes, Petzold uses just C in his API books. One thing to realize about the SDK style coding is that most of us who use it don't sit down every time we want to create an app and write everything from scratch. Most of it is 'boilerplate' type code that can be copied. That this is so is the basis of all the 'class frameworks' that attempt to improve on the SDK style. However, I highly recommend for those wishing to learn it that in the beginning one go through every statement in excrutiating detail and figure out what everything means so that there are no mysteries. In otherwords, figure out exactly what the HIWORD and LOWORD macros do. Figure out exactly what CALLBACK means; what __stdcall means; what WINAPI means; what a typedef is. This can be accomplished using the MSDN help. Do a search on those terms. The first chapter in Petzold's books explain these things to a large extent.

Learning to examine windows header files is also a skill that has to be learned. In the case of Windows, way on back (I'm talking about Win 3.0 times), there was just one Windows.h header. Now windows.h is just a master include that includes all the others such as winnt.h, etc. There are a lot of them. But the definitions of everything, i.e., #defines, typedefs, structs, function prototypes, are all in there, and are a valuable resource that the real experts use constantly when unsure of something.

Something else. It seems to me that in the world of C the concept of calling a function by its address was a commonly taught and used technique. In many C++ books I have seen this is never covered. I have a feeling many new C++ coders may be unaware of this, and it occurs to me that when confronted by this in SDK coding it might appear very mysterious. Its important because when you Register a class, one of the fields of WNDCLASSEX struct is the integral address of the CALLBACK ( __stdcall ) function Windows will call to pass message information. I don't know if this has been an issue or not; it just appears to me it could be.

I don't know if this will help, but I've posted some introductory material here ...

http://www.jose.it-berater.org/smfforum/index.php?topic=3389.0

It seems to have helped some; others thought it too complicated. You could judge for yourself.
And you know what? I really don't think SDK style coding is all that difficult. Its really pretty easy to get started. Ch1156, you mentioned you were using the Code::Blocks editor. The SDK template they provide when you start up a new Win32 GUI project, then pick the 'Frame' style instead of the dialog style, is an excellent place to start. It isn't bad at all. Its a bit verbose and large because they include lots of comments, and they extended the big important CreateWindowEx() call over multiple lines, but otherwise, there isn't all that much going on there, at least if you break it down into major 'steps'. The major steps are as folows...

1) A WNDCLASSEX struct needs to be allocated in WinMain() and filled out;

2) The address of this struct needs to be passed as a parameter to Api function RegisterClassEx() so that Windows knows the general characteristics of the Window Class;

3) The filling out of this WNDCLASSEX struct necessitates the creation of a Window Proceduire, i.e., a special function that adheres to a Microsoft defined calling convention and parameter list. The address of this function is one of the fields of the WNDCLASSEX struct to be registered;

4) Call CreateWindowEx() to create the window instance;

5) Drop into a message loop so that Windows can post messages to the Window's message quene.

I started with the Code::Blocks template and attempted to simplify it by removing extraneous material and comments to see how small I could make it. Here is my first cut at this. This compiles in Code::Blocks ...



Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <windows.h>
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
char szClassName[ ] = "CodeBlocksWindowsApp";

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpszArgument, int nCmdShow)
{
 HWND hwnd;
 MSG messages;
 WNDCLASSEX wc;

 wc.hInstance = hInstance;
 wc.lpszClassName = szClassName;
 wc.lpfnWndProc = WindowProcedure;
 wc.style = CS_DBLCLKS;
 wc.cbSize = sizeof (WNDCLASSEX);
 wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
 wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
 wc.lpszMenuName = NULL;
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
 RegisterClassEx(&wc);
 hwnd=CreateWindowEx(0,szClassName,"Template",WS_OVERLAPPEDWINDOW,50,50,544,375,HWND_DESKTOP,NULL,hInstance,NULL);
 ShowWindow (hwnd, nCmdShow);
 while(GetMessage (&messages, NULL, 0, 0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}


LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch(message)                  /* handle the messages */
 {
   case WM_DESTROY:
        PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
        break;
   default:                      /* for messages that we don't deal with */
        return DefWindowProc(hwnd, message, wParam, lParam);
 }

 return 0;
}
But you know, it can even be simplified and made smaller. While I don't always recommend this, it is instructive to realize that the declaration of the Window Procedure can be removed by simply replacing it with the implementation. That way the Window Procedure comes before WinMain().

Also, I personally don't use global variables at all in my Windows programs, so the szClassName character array can be made local to WinMain(). Here is that rendition ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <windows.h>

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch(message)
 {
   case WM_DESTROY:
        PostQuitMessage (0);
        break;
   default:
        return DefWindowProc(hwnd, message, wParam, lParam);
 }

 return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpszArgument, int nCmdShow)
{
 char szClassName[ ] = "CodeBlocksWindowsApp";
 WNDCLASSEX wc;
 MSG messages;
 HWND hwnd;

 wc.hInstance = hInstance;
 wc.lpszClassName = szClassName;
 wc.lpfnWndProc = WindowProcedure;
 wc.style = CS_DBLCLKS;
 wc.cbSize = sizeof (WNDCLASSEX);
 wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
 wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
 wc.lpszMenuName = NULL;
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
 RegisterClassEx(&wc);
 hwnd=CreateWindowEx(0,szClassName,"Template",WS_OVERLAPPEDWINDOW,50,50,544,375,HWND_DESKTOP,NULL,hInstance,NULL);
 ShowWindow (hwnd, nCmdShow);
 while(GetMessage (&messages, NULL, 0, 0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}
So we're down to something like 46 lines, including whitespace. It can be simplified further though- particularly the Window Procedure. Here's an even simpler version ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <windows.h>

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 if(message==WM_DESTROY)
    PostQuitMessage(0);
 else
    return DefWindowProc(hwnd, message, wParam, lParam);

 return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpszArgument, int nCmdShow)
{
 char szClassName[ ] = "CodeBlocksWindowsApp";
 WNDCLASSEX wc;
 MSG messages;
 HWND hwnd;

 wc.hInstance = hInstance;
 wc.lpszClassName = szClassName;
 wc.lpfnWndProc = WindowProcedure;
 wc.style = CS_DBLCLKS;
 wc.cbSize = sizeof (WNDCLASSEX);
 wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
 wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
 wc.lpszMenuName = NULL;
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
 RegisterClassEx(&wc);
 hwnd=CreateWindowEx(0,szClassName,"Template",WS_OVERLAPPEDWINDOW,50,50,544,375,HWND_DESKTOP,NULL,hInstance,NULL);
 ShowWindow (hwnd, nCmdShow);
 while(GetMessage (&messages, NULL, 0, 0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}


And that's only 42 lines of code. The trick to seeing how simple it is is to recognize the several steps I listed above such as registering the window class, calling CreateWindow(), and dropping into the message pump. Couldn't be simpler!
Last edited on
But you know, we don't have to stop there. Especially since we're on a roll! Lets simplify even more! For one thing, setting the Window Class style to CS_DBLCLKS is somewhat arbitrary. We can just set it to zero. Further, use of the WNDCLASSEX struct isn't exactly mandatory. For the simple demonstration window we are creating it would be just as well to use the smaller and simpler WNDCLASS struct. Here is that version, which brings us down to only 40 lines of code ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <windows.h>

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 if(message==WM_DESTROY)
    PostQuitMessage(0);
 else
    return DefWindowProc(hwnd, message, wParam, lParam);

 return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpszArgument, int nCmdShow)
{
 char szClassName[ ] = "CodeBlocksWindowsApp";
 MSG messages;
 WNDCLASS wc;
 HWND hwnd;

 wc.hInstance = hInstance;
 wc.lpszClassName = szClassName;
 wc.lpfnWndProc = WindowProcedure;
 wc.style = 0;
 wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
 wc.lpszMenuName = NULL;
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
 RegisterClass(&wc);
 hwnd=CreateWindow(szClassName,"Template",WS_OVERLAPPEDWINDOW,50,50,544,375,HWND_DESKTOP,NULL,hInstance,NULL);
 ShowWindow (hwnd, nCmdShow);
 while(GetMessage (&messages, NULL, 0, 0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}
Pages: 12