Stuck after the Hello World tutorial

Hello all,
I started reading about windows and programming for windows and I looked for Win32 tutorials. There's a really good one on Microsoft's website which I completed. It shows how you can spawn a window, what the message loop is and how to paint/close the window.

That's all good and I get it, but for the love of me, I can't find any other beginner tutorials to do after that. For example how to add buttons/textboxes etc. The API reference is OK but I have no idea what to do with it, where to put stuff.

Are there any references/tutorials that I can read through so I can get started?
I don't need much, just a few pointer on how things work and where things go.

Thanks.
Search for the Forger's Win32 Api Tutorial. Also, I've posted some tutorials here...

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

If you've learned how to create a window with CreateWindowEx(), you use that function to create other windows too, many of which have predefined Window Classes, i.e., you don't need to register their Window Classes with RegisterClassEx(). They have predefined class names such as "edit", "static" (label), "listbox", "button", "combobox", etc. So you can create instances of them that way. Its a very elegant setup.
Here's a simple example. It starts with the idea of a simple Hello, World! app that just shows a blank window. However, I put two buttons and two edit controls on it. Please don't be confused by the fact there is no switch statement in the WndProc. I rather prefer to map messages to the code which handles them through a for loop construct which calls the message handling function associated with the message. Note further the CreateWindowEx() calls which create the button and edit child window controls are in my WM_CREATE handler - fnWndProc_OnCreate(). This isn't necessary - they could be put in WinMain(). However, I choose not to do that because I prefer to use OOP principles. When fnWndProc_OnCreate() gets called, that is a call to an object constructor function. I feel that's a better place to construct the object than someplace not associated with it.

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//Form9.cpp -- compiler switches /O1 /Oi /Os /GL /D  8704 bytes; 116 lines
#include <windows.h>
#include <tchar.h>
#define IDC_LOVE  1500
#define IDC_HATE  1505
#define TXT_LOVE  1510
#define TXT_HATE  1515


#define dim(x) (sizeof(x) / sizeof(x[0]))

struct WndEventArgs
{
 HWND                         hWnd;
 WPARAM                       wParam;
 LPARAM                       lParam;
 HINSTANCE                    hIns;
};

long fnWndProc_OnCreate       (WndEventArgs& Wea);
long fnWndProc_OnCommand      (WndEventArgs& Wea);
long fnWndProc_OnDestroy      (WndEventArgs& Wea);

struct EVENTHANDLER
{
 unsigned int                 iMsg;
 long                         (*fnPtr)(WndEventArgs&);
};

const EVENTHANDLER EventHandler[]=
{
 {WM_CREATE,                  fnWndProc_OnCreate},
 {WM_COMMAND,                 fnWndProc_OnCommand},
 {WM_DESTROY,                 fnWndProc_OnDestroy}
};


long fnWndProc_OnCreate(WndEventArgs& Wea)
{
 Wea.hIns=((LPCREATESTRUCT)Wea.lParam)->hInstance;
 CreateWindowEx(0,_T("button"),_T("Love"),WS_CHILD|WS_VISIBLE,125,15,80,30,Wea.hWnd,(HMENU)IDC_LOVE,Wea.hIns,0);
 CreateWindowEx(WS_EX_CLIENTEDGE,"edit",_T(""),WS_CHILD|WS_VISIBLE,25,60,285,22,Wea.hWnd,(HMENU)TXT_LOVE,Wea.hIns,0);
 CreateWindowEx(0,_T("button"),_T("Hate"),WS_CHILD|WS_VISIBLE,125,105,80,30,Wea.hWnd,(HMENU)IDC_HATE,Wea.hIns,0);
 CreateWindowEx(WS_EX_CLIENTEDGE,"edit",_T(""),WS_CHILD|WS_VISIBLE,25,150,285,22,Wea.hWnd,(HMENU)TXT_HATE,Wea.hIns,0);

 return 0;
}


long fnWndProc_OnCommand(WndEventArgs& Wea)
{
 switch(LOWORD(Wea.wParam))
 {
   case IDC_LOVE:
     SetWindowText(GetDlgItem(Wea.hWnd,TXT_LOVE),_T("The World Needs More Love!"));
     MessageBox(Wea.hWnd,_T("...More Love!"),_T("This Is What You Want..."),MB_OK);
     break;
   case IDC_HATE:
     SetWindowText(GetDlgItem(Wea.hWnd,TXT_HATE),_T("The World Needs More Hate!"));
     MessageBox(Wea.hWnd,_T("...More Hate!"),_T("This Is What You Want..."),MB_OK);
     break;
 }

 return 0;
}


long fnWndProc_OnDestroy(WndEventArgs& Wea)
{
 DestroyWindow(Wea.hWnd);
 PostQuitMessage(0);
 return 0;
}


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 WndEventArgs Wea;

 for(unsigned int i=0; i<dim(EventHandler); i++)
 {
     if(EventHandler[i].iMsg==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(Wea);
     }
 }

 return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int __stdcall WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Form9");
 WNDCLASSEX wc;
 MSG messages;
 HWND hWnd;

 wc.lpszClassName=szClassName;                wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX);               wc.style=0;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);     wc.hInstance=hIns;
 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);  wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW;    wc.cbWndExtra=0;
 wc.lpszMenuName=NULL;                        wc.cbClsExtra=0;
 RegisterClassEx(&wc);
 hWnd=CreateWindowEx(0,szClassName,_T("Form9"),WS_OVERLAPPEDWINDOW,200,100,340,240,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
       TranslateMessage(&messages);
       DispatchMessage(&messages);
 }

 return messages.wParam;
}
I chucked the code into VS to give it a shot and I get this:

Error	1	error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?	c######win32project1.cpp	117	1	Win32Project1
	2	IntelliSense: argument of type "const char *" is incompatible with parameter of type "LPCWSTR"	##########\Win32Project1.cpp	42	35	Win32Project1
	3	IntelliSense: argument of type "const char *" is incompatible with parameter of type "LPCWSTR"	########\Win32Project1.cpp	44	35	Win32Project1
Last edited on
Well the first error is because you have your precompiled headers enabled and didn't include it.
In Visual Studio, set up a new project as an "Empty Project". Then add a new *.cpp file as the project's only file, and paste the code above into that. I just tested in Visual Studio 2008 and discovered I forgot the _T("") crap for two of the CreateWindowEX() calls in fnWndProc_OnCreate(). Here is the fixed procedure...

1
2
3
4
5
6
7
8
9
10
long fnWndProc_OnCreate(WndEventArgs& Wea)
{
 Wea.hIns=((LPCREATESTRUCT)Wea.lParam)->hInstance;
 CreateWindowEx(0,_T("button"),_T("Love"),WS_CHILD|WS_VISIBLE,125,15,80,30,Wea.hWnd,(HMENU)IDC_LOVE,Wea.hIns,0);
 CreateWindowEx(WS_EX_CLIENTEDGE,_T("edit"),_T(""),WS_CHILD|WS_VISIBLE,25,60,285,22,Wea.hWnd,(HMENU)TXT_LOVE,Wea.hIns,0);
 CreateWindowEx(0,_T("button"),_T("Hate"),WS_CHILD|WS_VISIBLE,125,105,80,30,Wea.hWnd,(HMENU)IDC_HATE,Wea.hIns,0);
 CreateWindowEx(WS_EX_CLIENTEDGE,_T("edit"),_T(""),WS_CHILD|WS_VISIBLE,25,150,285,22,Wea.hWnd,(HMENU)TXT_HATE,Wea.hIns,0);

 return 0;
}


It compiled fine in CodeBlocks because I didn't define UNICODE, but Visual Studio defaults to UNICODE so it errored out there.
Topic archived. No new replies allowed.