Can someone explain some stuff for me?

So, I am learning to program windows, and have made some basic stuff. But, in order to really, well, make real things, I need some things explained for me, because it seems like these are essential for programming Windows.

LPSTR: What is it? What is even USED for?
UINT: So, I kinda know what this is. unsigned integer, right?
HINSTANCE: So, I use this, but don't really understand what it is.
CALLBACK: I see a lot of tutorials use functions with CALLBACK. What does this do?
DWORD and LOWORD: I have no clue about these. Again, I use LOWORDs, but don't know what they are, and DWORDs I see in parameters. (isn't there a HIWORD as well?)
lParam and wParam: Aren't these like, 16 bit and 32 bit? What do they do?
LRESULT: I see this in the WndProc() function. Any telling what it is?

Last but not lease:
PWSTR: Not a clue about this one.

Anyway, that is really all my questions. If there are any other urgent WINAPI things I HAVE to know, please tell me them to and I will figure those out on my own time. Thanks for anything!

Oh, right, one last thing: I just got Windows Via C/C++ (great book), but in Chapter 3, it is on kernel objects. Well, to me, it didn't do a good job explaining it, and I would just like a general summary of it, because I somewhat understand it, just not entirely.
LPSTR: What is it? What is even USED for?


LPSTR = "Long Pointer to String"
LPCSTR = "Long Pointer to Const String"
LPTSTR = "Long Pointer to TCHAR String"
LPCTSTR = "Long Pointer to Const TCHAR String"
LPWSTR = "Long Pointer to Wide String"
LPCWSTR = "Long Pointer to Cosnt Wide String"

Don't worry about the 'long' bit... that's kind of retro. It doesn't really mean anything in modern Windows programming. Basically they're typdefs of the below:

1
2
3
4
5
6
typedef char*  LPSTR;
typedef const char* LPCSTR;
typedef TCHAR* LPTSTR;
typedef const TCHAR* LPCTSTR;
typedef wchar_t* LPWSTR;
typedef const wchar_t* LPCWSTR;


Most WinAPI functions take TCHAR strings in the form of LPCTSTRs. Though most (all) WinAPI functions have narrow and wide counterparts which take LPCSTR and LPCWSTR respectively.

IE:
MessageBox takes TCHAR strings (LPCTSTR)
MessageBoxA takes char strings (LPCSTR)
MessageBoxW takes wchar_t strings (LPCWSTR)




UINT


Yes this is just a typedef of unsigned int. Nothing really fancy about it.


HINSTANCE


The 'H' prefix indicates it's a "handle". Handles are a generic term... it's basically an arbitrary ID that is used to represent something.

In this case... your HINSTANCE represents the instance of your program. IE, if you run your program multiple times simultaneously, each program will have a unique instance.

CALLBACK


It's a define for a calling convention. I forget which one... maybe stdcall.

Calling conventions are used to determine how parameters are passed to functions (for example... they can specify the order in which they are placed on the stack). It's a very low level detail and you don't usually need to worry about it.

DWORD and LOWORD:


DWORD is a 'double word'.

A "byte" = 1 byte (8 bits)
A "word" = 2 bytes (16 bits)
A "DWORD" = 4 bytes (32 bits)
A "QWORD" (quad word) = 8 bytes (64 bits)

DWORD is usually a typedef for an unsigned long. Though it is guaranteed to be 32-bits, whereas the size of a long might change depending on the compiler/platform.



LOWORD is a macro to extract the low word (the low 16 bits) from a DWORD.
HIWORD is another macro for getting the high word.

For example:

1
2
3
4
5
6
7
DWORD example = 0x12345678;
WORD lo = LOWORD(example);
WORD hi = HIWORD(example);

// here...
//  lo == 0x5678
//  hi == 0x1234 



lParam and wParam


AFAIK, WPARAM and LPARAM are just typedef's of DWORD... but are used specifically for additional information with windows messages.

I don't think there's any practical reason for them to exist... other than that the type name 'WPARAM' gives a hint about what the variable is to represent.

LRESULT


Ditto.

AFAIK, LRESULT is the same as DWORD only it's used specifically for the return type from a windows message handler. Again I don't think there's any real difference to use it other than for clarity.

PWSTR


I've never seen this. But I'm guess it's the same as LPWSTR (explained above)




EDIT:

To clarify... I'm not 100% on what I said about WPARAM/LPARAM/LRESULT. If anyone else on here can correct me, I'd appreciate it.
Last edited on
So a lot of stuff is just variations on DWORD. Well, I guess that really simplifies it for me. Just... one more thing - for anyone to answer - I have been having trouble with dialogs and menus lately. Not really the coding, but defining (which is still the coding I guess haha). Anyway, I can't really find a good index of definitions (#define ). Like, it took me about 30 minutes to figure out how to properly define IDC_STATIC (#define IDC_STATIC -1 ). Basically, I don't know what values to use. For instance, all I know how to use is IDC_STUFF_GO as 9001 and IDC_FILE_EXIT as 9001 (maybe vice versa, I don't have my code open right now to double check). So, anyway, I guess what I am saying, is how to find values for all this. I am sorry if this isn't making sense, windows code is really overwhelming to me.
Disch gave a pretty good description of all that stuff!

In the past, a lot of folks started Windows programming by reading Charles Petzold's books namely "Windows Programming". Petzold knew that Windows programming was really pretty wierd, and there were a lot of things to be encountered that even professional C programmers didn't know, such as many of the things you asked and Disch tersely explained. I can see you are really sincere and trying AceDawg, so I'm thinking the best help I can give you is to suggest that a slight attitude adjustment might be best. The thing is, this is HARD! You may have finally hit something in life that you can't master in just a few weeks or even months, no matter how hard you try.

Another thing - and this is only my opinion for what its worth, is I think that C++ programmers have done a dis-service to beginners when they state that they shouldn't bother with C, the idea being that C++ is so much better than C, and by going directly to C++ one won't have to do as much unlearning. The reason I say that is because a lot of the beginners here who are stumbling so hard on the Win Api are doing so because they can't deal with it on its own terms, which is C based. The Win Api is what OOP looks like in C. You don't have string objects with methods, but rather pointers to character strings which are further confused by various and sundry typedefs. Typedefs everywhere!

The WPARAM and LPARAM WndProc parameters go 8 bytes with x64, by the way. I know because my compiler keeps warning me about it!

Don't know if this will help AceDawg, but I tried to put together some tutorials covering some basics here ...

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

Some folks told me it was pretty good stuff, others that it was a bit too advanced, and others that they couldn't understand it.
Yes, I was actually gonna go with Petzoid's Windows Programming, but, unfortunately, it was something like 95 dollars! Now, I may sound like a cheapskate when I say that, but I am 13. 95 dollars is not something I get easily. Anyway, I went for Richters Windows Via C/C++, as mentioned in my post. I am doing decent with that at the moment. That, irrelevantly, and I am saving up to build a pc, and I need all the cash I can get for that.

Anyway, thanks for the tutorial. But, like I said, is there a index for definitions? And another problem I have come across is making multiple dialogs. Any more help?
From what I remember, you should begin with 101 and use an unique ID for each definition.

Or use ResEdit and let it do the job for you.
With the resource files, normally you can just use any arbitrary number and go up from there. However, there are a few reserved ones, such as IDC_STATIC or IDOK, so in general start at about 100 and go from there (to be on the safe side).

What the actual values or the names are makes no difference: it just makes it easier to read. For example, I normally make my controls IDC_* and start from 4000, my menus IDM_* and start from 2000, my dialogs IDD_* and start from 100, and so on.

For using multiple dialogues, its just the same as using one. Just define the dialogue in the resource file and make sure that the controls have unique ID's. Note that the ID's don't have to be unique across all dialogues (though that can help readability), just be unique within the dialogue itself.

However, as @EssGeEich suggested, use a program like ResEdit ( http://www.resedit.net/ ) to do it for you, as it has a few advantages. It allows you to see the appearance of the dialogues without actually having to make the program, it automatically organises your ID's and things for you (making sure they are unique), and a whole bunch of other nifty little features.
Are you doing your windows with CreateWindowEx() or using Dialog resource files to create your Windows AceDawg? If the former I'll help you get your menues and dialogs working, but if not I can't help because I don't do the whole resource editor dialog thing. I basically hate it and don't use it.
I am using CreateWindowEx() to make a window, and then I make a dialog with dialog resource files and the message. I also don't use resource editors, I just make it from scratch.
Here's a first example. The three files are Main.cpp, Form13.h, and Form13.rc. The program creates a main menu and a dialog box brought up when you click Help >>> About. Tomorrow I'll post the same thing using the MAKEINTORESOURCE macros ...

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
//Form13.rc
#include "Windows.h"
#include "Form13.h"
#define  IDC_STATIC                                   -1

"Form13_Menu" MENU DISCARDABLE
{
 POPUP "&File"
 {
   POPUP "&Open"
   {
      MENUITEM  "&New...",                            IDM_FILE_NEW
      MENUITEM  "&Existing...",                       IDM_FILE_EXISTING
   }
   MENUITEM SEPARATOR
   MENUITEM "E&xit",                                  IDM_FILE_EXIT
 }
 POPUP "&Help"
 {
  MENUITEM "&Help...",                                IDM_HELP
  MENUITEM "&About...",                               IDM_HELP_ABOUT
 }
}

"Form13_Dialog" DIALOG DISCARDABLE 40,0,130,90
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter Personal Info"
FONT 8, "MS Sans Serif"
BEGIN
  LTEXT          "Name",IDC_STATIC,7,4,75,8
  EDITTEXT       IDC_NAME,85,4,40,12,ES_AUTOHSCROLL
  LTEXT          "Age",IDC_STATIC,7,23,75,8
  EDITTEXT       IDC_AGE,85,23,40,12,ES_AUTOHSCROLL
  LTEXT          "Sex",IDC_STATIC,7,42,75,8
  EDITTEXT       IDC_SEX,85,42,40,12,ES_AUTOHSCROLL
  DEFPUSHBUTTON  "OK",IDOK,65,70,40,14
  PUSHBUTTON     "Cancel",IDCANCEL,8,70,40,14
END


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
//Form13.h
#ifndef Form13_h
#define Form13_h

#define IDM_FILE_NEW          2000
#define IDM_FILE_EXISTING     2005
#define IDM_FILE_EXIT         2010
#define IDM_HELP              2100
#define IDM_HELP_ABOUT        2105
#define IDC_NAME              2200
#define IDC_AGE               2205
#define IDC_SEX               2210

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

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

typedef WndEventArgs*         lpWndEventArgs;

long fnWndProc_OnCreate       (lpWndEventArgs Wea);
long fnWndProc_OnCommand      (lpWndEventArgs Wea);
long fnWndProc_OnDestroy      (lpWndEventArgs Wea);

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

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


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
118
119
120
121
122
123
124
//Main.cpp
#include <windows.h>
#include <tchar.h>
#include "Form13.h"


long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
 return 0;
}


BOOL CALLBACK ModalDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
 TCHAR szName[64],szText[64];
 HWND hwndEdit;
 UINT nID;

 switch(message)
 {
  case WM_INITDIALOG:
    hwndEdit=GetDlgItem(hwndDlg,IDC_NAME);
    SetFocus(hwndEdit);
    return FALSE;
  case WM_COMMAND:
    nID = LOWORD(wParam);
    switch(nID)
    {
     case IDOK:
       hwndEdit=GetDlgItem(hwndDlg, IDC_NAME);
       GetWindowText(hwndEdit,szText,64);
       _tcscpy(szName,_T("Hello, "));
       _tcscat(szName,szText);
       _tcscat(szName,_T("!"));
       MessageBox(hwndDlg,szName,_T("Form13"),MB_OK);
     case IDCANCEL:
       EndDialog(hwndDlg, nID);
       break;
     default:
       break;
    }
    return TRUE;
  default:
    return FALSE;
 }
}


long fnWndProc_OnCommand(lpWndEventArgs Wea)
{
 switch(LOWORD(Wea->wParam))
 {
   case IDM_FILE_NEW:
     MessageBox(Wea->hWnd,_T("You Want A New File!"),_T("File New"),MB_OK);
     break;
   case IDM_FILE_EXISTING:
     MessageBox(Wea->hWnd,_T("You Want An Existing File!"),_T("File Existing"),MB_OK);
     break;
   case IDM_FILE_EXIT:
     MessageBox(Wea->hWnd,_T("You Want Out!"),_T("You're Outta Here!"),MB_OK);
     SendMessage(Wea->hWnd,WM_CLOSE,0,0);
     break;
   case IDM_HELP:
     MessageBox(Wea->hWnd,_T("You Need Help!"),_T("Help!!!"),MB_OK);
     break;
   case IDM_HELP_ABOUT:
     DialogBox(GetModuleHandle(NULL),_T("Form13_Dialog"),Wea->hWnd,ModalDlgProc);
     break;
 }

 return 0;
}


long fnWndProc_OnDestroy(lpWndEventArgs Wea)
{
 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 WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Form13");
 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="Form13_Menu";               wc.cbClsExtra=0;
 RegisterClassEx(&wc);
 hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,75,75,320,305,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}

My 'message cracker' scheme above confuses most beginners. Its ultimately the best way to go, but since beginners don't know what to make of it, I translated the above back to standard SDK with the ridiculous switch in the WndProc. Here is that. Same exact program as above but with switch...

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
//Main.cpp
#include <windows.h>
#include <tchar.h>
#include "Form14.h"


BOOL CALLBACK ModalDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
 TCHAR szName[64],szText[64];
 HWND hwndEdit;
 UINT nID;

 switch(message)
 {
  case WM_INITDIALOG:
    hwndEdit=GetDlgItem(hwndDlg,IDC_NAME);
    SetFocus(hwndEdit);
    return FALSE;
  case WM_COMMAND:
    nID = LOWORD(wParam);
    switch(nID)
    {
     case IDOK:
       hwndEdit=GetDlgItem(hwndDlg, IDC_NAME);
       GetWindowText(hwndEdit,szText,64);
       _tcscpy(szName,_T("Hello, "));
       _tcscat(szName,szText);
       _tcscat(szName,_T("!"));
       MessageBox(hwndDlg,szName,_T("Form14"),MB_OK);
     case IDCANCEL:
       EndDialog(hwndDlg, nID);
       break;
     default:
       break;
    }
    return TRUE;
  default:
    return FALSE;
 }
}



LRESULT CALLBACK fnWndProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
   case WM_COMMAND:
    {
        switch(LOWORD(wParam))
        {
          case IDM_FILE_NEW:
            MessageBox(hWnd,_T("You Want A New File!"),_T("File New"),MB_OK);
            return 0;
          case IDM_FILE_EXISTING:
            MessageBox(hWnd,_T("You Want An Existing File!"),_T("File Existing"),MB_OK);
            return 0;
          case IDM_FILE_EXIT:
            MessageBox(hWnd,_T("You Want Out!"),_T("You're Outta Here!"),MB_OK);
            SendMessage(hWnd,WM_CLOSE,0,0);
            return 0;;
          case IDM_HELP:
            MessageBox(hWnd,_T("You Need Help!"),_T("Help!!!"),MB_OK);
            break;
          case IDM_HELP_ABOUT:
            DialogBox(GetModuleHandle(NULL),_T("Form13_Dialog"),hWnd,ModalDlgProc);
            return 0;
        }
     }
     break;
   case WM_DESTROY:
     {
        PostQuitMessage(0);
        return 0;
     }
 }

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


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Form14");
 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="Form13_Menu";               wc.cbClsExtra=0;
 RegisterClassEx(&wc);
 hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,75,75,320,305,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Form14.h
#ifndef Form14_h
#define Form14_h

#define IDM_FILE_NEW          2000
#define IDM_FILE_EXISTING     2005
#define IDM_FILE_EXIT         2010
#define IDM_HELP              2100
#define IDM_HELP_ABOUT        2105
#define IDC_NAME              2200
#define IDC_AGE               2205
#define IDC_SEX               2210

#endif 


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
#include "Windows.h"
#include "Form14.h"
#define  IDC_STATIC                                   -1

"Form13_Menu" MENU DISCARDABLE
{
 POPUP "&File"
 {
   POPUP "&Open"
   {
      MENUITEM  "&New...",                            IDM_FILE_NEW
      MENUITEM  "&Existing...",                       IDM_FILE_EXISTING
   }
   MENUITEM SEPARATOR
   MENUITEM "E&xit",                                  IDM_FILE_EXIT
 }
 POPUP "&Help"
 {
  MENUITEM "&Help...",                                IDM_HELP
  MENUITEM "&About...",                               IDM_HELP_ABOUT
 }
}

"Form13_Dialog" DIALOG DISCARDABLE 40,0,130,90
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter Personal Info"
FONT 8, "MS Sans Serif"
BEGIN
  LTEXT          "Name",IDC_STATIC,7,4,75,8
  EDITTEXT       IDC_NAME,85,4,40,12,ES_AUTOHSCROLL
  LTEXT          "Age",IDC_STATIC,7,23,75,8
  EDITTEXT       IDC_AGE,85,23,40,12,ES_AUTOHSCROLL
  LTEXT          "Sex",IDC_STATIC,7,42,75,8
  EDITTEXT       IDC_SEX,85,42,40,12,ES_AUTOHSCROLL
  DEFPUSHBUTTON  "OK",IDOK,65,70,40,14
  PUSHBUTTON     "Cancel",IDCANCEL,8,70,40,14
END
Now, here's the same exact program but using the MAKEINTRESOURCE macro to convert strings representing menu and dialog box names to a numeric representation...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Form15.h
#ifndef Form15_h
#define Form15_h

#define Form15_Menu           1800
#define Form15_Dialog         1900
#define IDM_FILE_NEW          2000
#define IDM_FILE_EXISTING     2005
#define IDM_FILE_EXIT         2010
#define IDM_HELP              2100
#define IDM_HELP_ABOUT        2105
#define IDC_NAME              2200
#define IDC_AGE               2205
#define IDC_SEX               2210

#endif 


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
//Form15.rc
#include "Windows.h"
#include "Form15.h"
#define  IDC_STATIC   -1

Form15_Menu MENU DISCARDABLE
{
 POPUP "&File"
 {
   POPUP "&Open"
   {
      MENUITEM  "&New...",         IDM_FILE_NEW
      MENUITEM  "&Existing...",    IDM_FILE_EXISTING
   }
   MENUITEM SEPARATOR
   MENUITEM "E&xit",               IDM_FILE_EXIT
 }
 POPUP "&Help"
 {
  MENUITEM "&Help...",             IDM_HELP
  MENUITEM "&About...",            IDM_HELP_ABOUT
 }
}

Form15_Dialog DIALOG DISCARDABLE 40,0,130,90
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter Personal Info"
FONT 8, "MS Sans Serif"
BEGIN
  LTEXT          "Name",IDC_STATIC,7,4,75,8
  EDITTEXT       IDC_NAME,85,4,40,12,ES_AUTOHSCROLL
  LTEXT          "Age",IDC_STATIC,7,23,75,8
  EDITTEXT       IDC_AGE,85,23,40,12,ES_AUTOHSCROLL
  LTEXT          "Sex",IDC_STATIC,7,42,75,8
  EDITTEXT       IDC_SEX,85,42,40,12,ES_AUTOHSCROLL
  DEFPUSHBUTTON  "OK",IDOK,65,70,40,14
  PUSHBUTTON     "Cancel",IDCANCEL,8,70,40,14
END


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
//Main.cpp
#include <windows.h>
#include <tchar.h>
#include "Form15.h"


BOOL CALLBACK ModalDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
 TCHAR szName[64],szText[64];
 HWND hwndEdit;
 UINT nID;

 switch(message)
 {
  case WM_INITDIALOG:
    hwndEdit=GetDlgItem(hwndDlg,IDC_NAME);
    SetFocus(hwndEdit);
    return FALSE;
  case WM_COMMAND:
    nID = LOWORD(wParam);
    switch(nID)
    {
     case IDOK:
       hwndEdit=GetDlgItem(hwndDlg, IDC_NAME);
       GetWindowText(hwndEdit,szText,64);
       _tcscpy(szName,_T("Hello, "));
       _tcscat(szName,szText);
       _tcscat(szName,_T("!"));
       MessageBox(hwndDlg,szName,_T("Form15"),MB_OK);
     case IDCANCEL:
       EndDialog(hwndDlg, nID);
       break;
     default:
       break;
    }
    return TRUE;
  default:
    return FALSE;
 }
}



LRESULT CALLBACK fnWndProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
   case WM_COMMAND:
    {
        switch(LOWORD(wParam))
        {
          case IDM_FILE_NEW:
            MessageBox(hWnd,_T("You Want A New File!"),_T("File New"),MB_OK);
            return 0;
          case IDM_FILE_EXISTING:
            MessageBox(hWnd,_T("You Want An Existing File!"),_T("File Existing"),MB_OK);
            return 0;
          case IDM_FILE_EXIT:
            MessageBox(hWnd,_T("You Want Out!"),_T("You're Outta Here!"),MB_OK);
            SendMessage(hWnd,WM_CLOSE,0,0);
            return 0;;
          case IDM_HELP:
            MessageBox(hWnd,_T("You Need Help!"),_T("Help!!!"),MB_OK);
            break;
          case IDM_HELP_ABOUT:
            DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(Form15_Dialog),hWnd,ModalDlgProc);
            return 0;
        }
     }
     break;
   case WM_DESTROY:
     {
        PostQuitMessage(0);
        return 0;
     }
 }

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


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Form15");
 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=MAKEINTRESOURCE(Form15_Menu),  wc.cbClsExtra=0;
 RegisterClassEx(&wc);
 hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,75,75,320,305,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}
Now, since I hate menu resources, dialog resources, and a lot of other stuff I oftentimes create them programatically in code. Here is about the same program but with the menu and dialog box created programatically ...

It won't all fit so I've got to break into two piecies. This one goes back to my message cracker scheme...

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
// Form16.h
#ifndef Main_h
#define Main_h

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

#define IDC_STATIC            -1
#define ID_FILE_OPEN          1500
#define ID_FILE_SAVE          1505
#define ID_FILE_EXIT          1510
#define ID_OPTIONS            1600
#define IDD_ABOUT             1700
#define IDD_DIALOGABOUT       1700
#define IDD_GROUP             1705
#define IDD_OK                1710
#define IDD_CANCEL            1715

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

typedef WndEventArgs*         lpWndEventArgs;

long fnWndProc_OnCreate       (lpWndEventArgs Wea);
long fnWndProc_OnCommand      (lpWndEventArgs Wea);
long fnWndProc_OnPaint        (lpWndEventArgs Wea);
long fnWndProc_OnDestroy      (lpWndEventArgs Wea);

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

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



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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//Main.cpp
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <tchar.h>
#include <commdlg.h>
#include "Form16.h"


LRESULT CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
    case WM_CREATE:
      EnableWindow(GetParent(hwnd),FALSE);
      return 0;
    case WM_COMMAND:
      switch(LOWORD(wParam))
      {
         case IDD_OK:
           MessageBox(hwnd,_T("You Clicked The OK Button!"),_T("OK Button Click!"),MB_OK);
           SendMessage(hwnd,WM_CLOSE,0,0);
           break;
         case IDD_CANCEL:
           MessageBox(hwnd,_T("You Clicked The Cancel Button!"),_T("Cancel Button Click!"),MB_OK);
           SendMessage(hwnd,WM_CLOSE,0,0);
           break;
      }
      return 0;
    case WM_CLOSE:
      EnableWindow(GetParent(hwnd),TRUE);
      DestroyWindow(hwnd);
      return 0;
    case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
 }

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


long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
 TCHAR szClassName[]=_T("Dialog");
 TCHAR* ptrOpenFileName=NULL;
 HMENU hMenu, hSubMenu;
 WNDCLASSEX wc;

 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
 hMenu = CreateMenu();
 hSubMenu = CreatePopupMenu();
 AppendMenu(hSubMenu,  MF_STRING,            (UINT_PTR)ID_FILE_OPEN,  _T("&Open"));
 AppendMenu(hSubMenu,  MF_STRING,            ID_FILE_SAVE,            _T("&Save"));
 AppendMenu(hSubMenu,  MF_SEPARATOR,         0,                                 0);
 AppendMenu(hSubMenu,  MF_STRING,            (UINT_PTR)ID_FILE_EXIT,  _T("E&xit"));
 AppendMenu(hMenu,     MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu,      _T("&File"));

 hSubMenu = CreatePopupMenu();
 AppendMenu(hSubMenu,  MF_STRING,            (UINT_PTR)ID_OPTIONS,_T("&Explorer"));
 AppendMenu(hMenu,     MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu,   _T("O&ptions"));

 hSubMenu = CreatePopupMenu();
 AppendMenu(hSubMenu,  MF_STRING,            (UINT_PTR)IDD_ABOUT,    _T("&About"));
 AppendMenu(hMenu,     MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu,      _T("&Help"));
 SetMenu(Wea->hWnd, hMenu);

 //Then Register Window Class For Dialog Box
 wc.lpszClassName=szClassName,               wc.lpfnWndProc=DlgProc;
 wc.cbSize=sizeof(wc),                       wc.style=CS_HREDRAW | CS_VREDRAW;
 wc.cbClsExtra=0,                            wc.cbWndExtra=0;
 wc.hInstance=Wea->hIns,                     wc.hCursor=LoadCursor(NULL, IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW,   wc.lpszMenuName=NULL;
 wc.hIcon=0;                                 wc.hIconSm=0;
 RegisterClassEx(&wc);

 //And finally Allocate Memory To Store File Name from Open File Dialog for
 ptrOpenFileName=(TCHAR*)GlobalAlloc(GPTR,256*sizeof(TCHAR)); //later display in WM_PAINT
 if(ptrOpenFileName)                                          //handler on the main window
    SetWindowLongPtr(Wea->hWnd,GWLP_USERDATA,(LONG_PTR)ptrOpenFileName);
 else
    return -1;

 return 0;
}


long WndProc_OnFileOpen(lpWndEventArgs Wea)
{
 static TCHAR szFilter[]=_T("C Files (*.C),CPP Files (*.cpp)\0*.c;*.cpp\0\0");
 static TCHAR szTitleName[_MAX_FNAME+_MAX_EXT];
 static TCHAR szFileName[_MAX_PATH];
 TCHAR* ptrOpenFileName=NULL;
 TCHAR lpszBuffer[256];
 OPENFILENAME ofn;

 GetCurrentDirectory(256*sizeof(TCHAR),lpszBuffer);
 memset(&ofn,_T('\0'),sizeof(OPENFILENAME));
 ofn.lStructSize=sizeof(OPENFILENAME);
 ofn.lpstrFilter = szFilter;
 ofn.nMaxFile=_MAX_PATH;
 ofn.nMaxFileTitle=_MAX_FNAME+_MAX_EXT;
 ofn.lpstrInitialDir = lpszBuffer;
 ofn.lpstrDefExt = _T("cpp");
 ofn.hInstance=GetModuleHandle(_T(""));
 ofn.hwndOwner = Wea->hWnd;
 ofn.Flags=OFN_HIDEREADONLY | OFN_CREATEPROMPT;
 ofn.lpstrFile=szFileName;
 ofn.lpstrFileTitle=szTitleName;
 GetOpenFileName(&ofn);
 ptrOpenFileName=(TCHAR*)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
 _tcscpy(ptrOpenFileName,ofn.lpstrFile);
 InvalidateRect(Wea->hWnd,NULL,FALSE);

 return 0;
}


long WndProc_OnFileSave(lpWndEventArgs Wea)
{
 static TCHAR szFilter[]=_T("C Files (*.C),CPP Files (*.cpp)\0*.c;*.cpp\0\0");
 static TCHAR szTitleName[_MAX_FNAME+_MAX_EXT];
 static TCHAR szFileName[_MAX_PATH];
 TCHAR* ptrOpenFileName=NULL;
 TCHAR lpszBuffer[256];
 OPENFILENAME ofn;

 GetCurrentDirectory(256*sizeof(TCHAR),lpszBuffer);
 memset(&ofn,_T('\0'),sizeof(OPENFILENAME));
 ofn.lStructSize=sizeof(OPENFILENAME);
 ofn.lpstrFilter = szFilter;
 ofn.nMaxFile=_MAX_PATH;
 ofn.nMaxFileTitle=_MAX_FNAME+_MAX_EXT;
 ofn.lpstrInitialDir = lpszBuffer;
 ofn.lpstrDefExt = _T("cpp");
 ofn.hInstance=GetModuleHandle(_T(""));
 ofn.hwndOwner = Wea->hWnd;
 ofn.Flags=OFN_HIDEREADONLY | OFN_CREATEPROMPT;
 ofn.lpstrFile=szFileName;
 ofn.lpstrFileTitle=szTitleName;
 GetSaveFileName(&ofn);
 ptrOpenFileName=(TCHAR*)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
 _tcscpy(ptrOpenFileName,ofn.lpstrFile);
 InvalidateRect(Wea->hWnd,NULL,FALSE);

 return 0;
}


long WndProc_OnAbout(lpWndEventArgs Wea)
{
 TCHAR szCap2[]=_T("An Example Program Showing How To");
 TCHAR szCap1[]=_T("About This Program");
 DWORD dwExStyle,dwStyle,dwSty;
 HWND hDlg,hGroup;
 MSG Msg;

 dwExStyle = WS_EX_DLGMODALFRAME | WS_EX_CONTROLPARENT;
 dwStyle   = WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE;
 dwSty     = WS_CHILD|WS_VISIBLE;
 Wea->hIns=GetModuleHandle(_T(""));
 hDlg=CreateWindowEx(dwExStyle,_T("Dialog"),_T("Dialog Window"),dwStyle,175,100,400,145,Wea->hWnd,0,Wea->hIns,NULL);
 hGroup=CreateWindow(_T("button"),szCap1,BS_GROUPBOX|dwSty,5,5,385,100,hDlg,(HMENU)IDD_GROUP,Wea->hIns,0);
 CreateWindow(_T("button"),_T("OK"),WS_TABSTOP|dwSty,295,25,80,25,hDlg,(HMENU)IDD_OK,Wea->hIns,0);
 CreateWindow(_T("button"),_T("Cancel"),WS_TABSTOP|dwSty,295,65,80,25,hDlg,(HMENU)IDD_CANCEL,Wea->hIns,0);
 CreateWindow(_T("static"),szCap2,dwSty,25,25,275,25,hGroup,(HMENU)-1,Wea->hIns,0);
 CreateWindow(_T("static"),_T("              Use Dialog Boxes"),dwSty,25,42,275,25,hGroup,(HMENU)-1,Wea->hIns,0);
 CreateWindow(_T("static"),_T("                     By Fred"),dwSty,25,72,275,25,hGroup,(HMENU)-1,Wea->hIns,0);
 while(GetMessage(&Msg, NULL, 0, 0))
 {
    if(!IsDialogMessage(hDlg,&Msg))
    {
       TranslateMessage(&Msg);
       DispatchMessage(&Msg);
    }
 }

 return 0;
}


long WndProc_OnOptions(lpWndEventArgs Wea)
{
 system("explorer c:\\");
 return 0;
}


long WndProc_OnExit(lpWndEventArgs Wea)
{
 SendMessage(Wea->hWnd,WM_CLOSE,0,0);
 return 0;
}
continued Main.cpp...

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

long fnWndProc_OnPaint(lpWndEventArgs Wea)
{
 TCHAR* ptrOpenFileName=NULL;
 PAINTSTRUCT ps;
 HDC hDC;

 hDC=BeginPaint(Wea->hWnd,&ps);
 ptrOpenFileName=(TCHAR*)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
 TextOut(hDC,2,2,ptrOpenFileName,(int)_tcslen(ptrOpenFileName));
 EndPaint(Wea->hWnd,&ps);

 return 0;
}


long fnWndProc_OnDestroy(lpWndEventArgs Wea)
{
 TCHAR* ptrOpenFileName=NULL;

 ptrOpenFileName=(TCHAR*)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
 GlobalFree(ptrOpenFileName);
 PostQuitMessage(0);

 return 0;
}


LRESULT CALLBACK WndProc(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 WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpCmdLine, int nCmdShow)
{
 TCHAR szClass[]=_T("Dialogs");
 WNDCLASSEX wc;
 HWND hWnd;
 MSG Msg;

 wc.lpszClassName=szClass,               wc.lpfnWndProc=WndProc;;
 wc.cbSize=sizeof(WNDCLASSEX),           wc.style=0;
 wc.cbClsExtra=0,                        wc.cbWndExtra=0;
 wc.hInstance=hIns,                      wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 wc.hCursor=LoadCursor(NULL,IDC_ARROW),  wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
 wc.lpszMenuName=NULL,                   wc.hIconSm=NULL;
 RegisterClassEx(&wc);
 hWnd=CreateWindow(szClass,_T("Non-Dialog Engine Dialog Boxes"),WS_OVERLAPPEDWINDOW,350,350,400,200,NULL,NULL,hIns,NULL);
 ShowWindow(hWnd,nCmdShow);
 while(GetMessage(&Msg, NULL, 0, 0))
 {
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
 }

 return (int)Msg.wParam;
}
Wow. That is a lot of code. I happen to sort of like the message resources, they seem pretty simple other than the macros. I will probably be like you and make them programatically when I move away from the beginner state. Anyway, I am actually surprised. I never get this many replies. My average is like 4. So thanks, you've been a big help.
Topic archived. No new replies allowed.