Proper Windows Programming Design

I want to know how to properly design a windows application.


Like in console programming creating .h and .cpp files was easy but feels like another paradigm almost when programming a windows app.


I want to see how code is organized. I want to create child window of a different color than the main like a black box inside a white window for instance. The code loos so sloppy when creating another window class to do this.

I have no idea how to design this.

Thanks for reading.
I like to wrap everything up in classes with each class defined in a separate .h file and implemented in a corresponding .cpp file.

I start with a base CWindow class which implements the functionality that all windows and controls have in common. This includes Create(), Move(), and Resize() methods, among others, and a private HWND data member.

For every control my application uses I derive a new class from CWindow and add functionality specific to that control. For example, a list control would have InsertItem() and DeleteItem() methods.

Top-level windows also derive from CWindow and implement their own window procedures. They also contain objects of the various control classes as private data members. Top-level windows are responsible for initializing and arranging the controls they contain.

If I have multiple top-level windows I'll add functionality to each so they can communicate with each other where necessary. Sometimes I'll take it a step further and contain them all in a CApplication class, which I use to initialize and drive the entire application.
Last edited on
The first important question is: which library / framework do you want to use?

Classic Win32 SDK (the one with WinMain(), WindowProc(), GetMessage(), ...)
or
MFC (that uses CWinApp, CWnd, MESSAGE_MAP, ...)
or
.net (with System::Windows::Forms, Forms::Button, System::EventHandler(), ... )
or
worse?

All of them usually use a slightly different approach.
In .net for example you usually implement most of the code in the .h files with one file per class.
With Win32 and MFC it's usually a more traditional approach with .h for interface and declaration and .cpp for implementation.

So, which library is it?
Thanks for the reply..I Haven't looked into libraries yet because I just want to get the basics of the win api down.

So if I wanted to create a child window..I would program that window in a .h file and then call the function to have the window be displayed in the main.cpp file?

And the child window would have its own winProc?
Last edited on
There's a paradigm shift involved here. Its harder than you think. There are basics that have to be learned before you can even begin. If you try to begin without learning the basics plan on a long time spinning your wheels, getting confused (as you obviously are now), getting nowhere, and heaven forbid, ending up using class frameworks because you can't get anything else to work.

Most folks here recommend starting with some online tutorials. One recommended here a lot is the Forger's Win32 Tutorial. You can search on that and come up with a link. I've written some getting started material and put it here ...

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

All the old timers (like me) swear by Charles Petzold's "Programming Windows" book, but that is getting harder to get, I believe (its old).

Plexus above gave a succinct description of your options. Knn9 described the Class Framework approach. I personally do Win32 Api SDK style, with my own modifications of it. It produces the smallest, fastest executables. If you would work through the examples I've posted at the link above, plus perhaps something like the Forger's Win32 Tutorial, you would get it.
closed account (z05DSL3A)
All the old timers (like me) swear by Charles Petzold's "Programming Windows" book, but that is getting harder to get, I believe (its old).
*Thumbs Up*
So if I wanted to create a child window..I would program that window in a .h file and then call the function to have the window be displayed in the main.cpp file?

I don't know what function you're referring to but you don't put executable code in an .h file. Those are for function prototypes, class definitions, typedefs, etc.

At the very least I would separate the implementation of each window into separate cpp files, E.g., mainwindow.cpp and childwindow.cpp. Put all of the functions related to each window in those files. Put all the function prototypes in mainwindow.h and childwindow.h. Include each of the .h files in the respective cpp file and both in main.cpp(the one with WinMain() and the message pump).

And the child window would have its own winProc?

Not necessarily. If it's a control, Windows has a default window procedure, hence why you don't supply your own window class when you create them.

It's possible for windows you create to share the same window procedure by passing the same window class to CreateWindowEx() for both windows. In the window procedure you get the handle of the window receiving the message. This is what I do when I use classes because it's possible to store a pointer to the CWindow object in the HWND itself and retrieve it in the window procedure.
Last edited on
I'll post the proper way code should be organized for Win32/64 SDK style apps. The sample app created will perform the following functions...

1) Create a Main Program Window containing three button controls with respective captions 'Option #1', 'Option #2', and 'Option #3';

2) Clicking button Option #1 creates a new WS_OVERLAPPEDWINDOW top level window/dialog/form which is modal, i.e., it disables the main startup Form or Main Window;

3) Clicking Option #2 creates a new WS_OVERLAPPEDWINDOW top level window which hides the main startup Form or main program window;

4) Clicking Option #3 creates a new WS_OVERLAPPEDWINDOW top level window which neither disables the main window nor hides it. Therefore you can click on the Option #3 button as long as you want and create as many of these as you want;

5) All the windows/dialogs/forms use TextOut() to show displaying text on a form;

6) The program shows how to create Child Window Controls;

7) The program shows how to modularize one's code into event handling procedures. This is to overcome the unscalability and ungainliness of the typical Window Procedure switch construct, which, in my opinion, shouldn't be used except for the very smallest of test or example code;

8) Program shows how to code without global variables. There are no global variables in this code;

9) Program shows how to organize code into code modules of *.cpp and *.h files based on seperate Window Procedures;

10) Program can be compiled either wide character or ansi, x86 or x64. Tested with GNU GCC (old and x64 versions) and VC9;

11) Program shows how to pass data among windows/dialogs/forms using the CREATESTRUCT params (last parameter of CreateWindow() call.

Project has eight files as follows...

Main.cpp
Main.h
Form1.cpp
Form1.h
Form2.cpp
Form2.h
Form3.cpp
Form3.h

Copy code from forum and name files as such. Put in project directory where you've created a blank Win32/64 project, and use IDE to add files to project....

continued...

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
//Main.cpp                //Program displays a main Form/Window/Dialog With Three Buttons on it to simulate
#include <windows.h>      //a program started from a main Form with three modules/options/modalities within
#include <tchar.h>        //which it operates.  When you click the top button a new Form/Window/Dialog is
#include <stdio.h>        //created with CreateWindow() of the "Form1" Window Class, and in the WM_CREATE
#include "Main.h"         //handler of this new window it disables the main form with the three buttons and
#include "Form1.h"        //therefore is an example of a modal dialog.  When you dismiss this modal dialog
#include "Form2.h"        //and click on Button/Option #2 on the Main Form, a CreateWindow() call creates a
#include "Form3.h"        //window of "Form2" Window Class, and in the WM_CREATE handler...


long fnWndProc_OnCreate(lpWndEventArgs Wea) //...for this window it hides or makes invisible the main
{                                           //window.  After dismssing this window you'll find that you
 DWORD dwStyle=WS_CHILD|WS_VISIBLE;         //can click on the Option #3 button as many times as you like
 TCHAR szClassName[16];                     //because the window-form-dialog it creates neither disables
 WNDCLASSEX wc;                             //nor makes invisible the main window.  Further note that these
                                            //Option #3 windows can be interacted with regardless of what-
 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance; //ever is going on with the other windows.
 CreateWindow(_T("button"),_T("Option #1"),dwStyle,65,15,120,25,Wea->hWnd,(HMENU)IDC_BUTTON_FORM1,Wea->hIns,0);
 CreateWindow(_T("button"),_T("Option #2"),dwStyle,65,55,120,25,Wea->hWnd,(HMENU)IDC_BUTTON_FORM2,Wea->hIns,0);
 CreateWindow(_T("button"),_T("Option #3"),dwStyle,65,95,120,25,Wea->hWnd,(HMENU)IDC_BUTTON_FORM3,Wea->hIns,0);

 //Register Window Classes For Form1, Form2 and Form3
 wc.cbSize=sizeof(WNDCLASSEX),                            wc.style=CS_HREDRAW | CS_VREDRAW;
 wc.cbClsExtra=0,                                         wc.cbWndExtra=0;
 wc.hInstance=Wea->hIns,                                  wc.hIcon=LoadIcon(NULL, IDI_APPLICATION);
 wc.hIconSm=0,                                            wc.hCursor=LoadCursor(NULL, IDC_ARROW);
 wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH),    wc.lpszMenuName=NULL;
 _tcscpy(szClassName,_T("Form1")),                        wc.lpszClassName=szClassName;
 wc.lpfnWndProc=fnForm1_WndProc;
 RegisterClassEx(&wc);

 _tcscpy(szClassName,_T("Form2"));
 wc.lpfnWndProc=fnForm2_WndProc;
 wc.lpszClassName=szClassName;                //Note that a WM_CREATE call is akin to a constructor call in typical
 RegisterClassEx(&wc);                        //C++ class architecture.  When you receive this call/message Windows
                                              //has finished doing what it needs to support the Window object, and
 _tcscpy(szClassName,_T("Form3"));            //is 'passing the ball' to you.  In my apps with multiple windows I
 wc.lpszClassName=szClassName;                //typically use the WM_CREATE handler to register any window classes
 wc.lpfnWndProc=fnForm3_WndProc;              //I need in the app, so that I can make CreateWindow() calls when I
 RegisterClassEx(&wc);                        //need to instantiate a window of some type.

 return 0;
}


long btnForm1_Click(lpWndEventArgs Wea)       //This is an 'Event Handler' for a click of the top button on the
{                                             //main Form.  It uses CreateWindowEx() to instantiate a new Window
 HWND hWnd;                                   //of class "Form1"  Note that the last parameter of the call is
                                              //Wea->hWnd.  That is the HWND of the main program Window.  The
 hWnd=CreateWindowEx                          //last parameter is the Creation Parameters parameter.  It can be
 (                                            //retrieved (as can all the others) through the CREATIONSTRUCT a
   0,                                         //pointer to which is received in the lParam of the WM_CREATE
   _T("Form1"),                               //message for the newly instantiating Window. 
   _T("Form1"),
   WS_OVERLAPPEDWINDOW,
   50,25,310,185,
   Wea->hWnd,
   (HMENU)0,
   GetModuleHandle(0),
   Wea->hWnd
 );
 ShowWindow(hWnd,SW_SHOWNORMAL);
 UpdateWindow(hWnd);

 return 0;
}


long btnForm2_Click(lpWndEventArgs Wea)
{
 HWND hWnd;

 hWnd=CreateWindowEx
 (
   0,
   _T("Form2"),
   _T("Form2"),
   WS_OVERLAPPEDWINDOW,
   200,250,310,185,
   Wea->hWnd,
   (HMENU)0,
   GetModuleHandle(0),
   Wea->hWnd
 );
 ShowWindow(hWnd,SW_SHOWNORMAL);
 UpdateWindow(hWnd);

 return 0;
}


long btnForm3_Click(lpWndEventArgs Wea)
{
 HWND hWnd;

 hWnd=CreateWindowEx
 (
   0,
   _T("Form3"),
   _T("Form3"),
   WS_OVERLAPPEDWINDOW,
   CW_USEDEFAULT,CW_USEDEFAULT,300,260,
   0,
   (HMENU)0,
   GetModuleHandle(0),
   Wea->hWnd
 );
 ShowWindow(hWnd,SW_SHOWNORMAL);
 UpdateWindow(hWnd);

 return 0;
}


long fnWndProc_OnCommand(lpWndEventArgs Wea)
{
 switch(LOWORD(Wea->wParam))
 {
    case IDC_BUTTON_FORM1:
      return btnForm1_Click(Wea);
    case IDC_BUTTON_FORM2:
      return btnForm2_Click(Wea);
    case IDC_BUTTON_FORM3:
      return btnForm3_Click(Wea);
 }

 return 0;
}


long fnWndProc_OnClose(lpWndEventArgs Wea)       //Search And Destroy Mission For Any Form3
{                                                //Windows Hanging Around.
 HWND hForm;

 if(MessageBox(Wea->hWnd,_T("Do You Wish To Exit?"),_T("Exit App?"),MB_YESNO)==IDYES)
 {
    do                                           //If FindWindow() returns something other
    {                                            //than zero, it found a window matching
      hForm=FindWindow(_T("Form3"),_T("Form3")); //the description of what you are looking
      if(hForm)                                  //for.  In that case, send a WM_CLOSE
         SendMessage(hForm,WM_CLOSE,0,0);        //message.  If NULL is returned then just
      else                                       //break out of the loop and terminate the
         break;                                  //app.
    }while(TRUE);
    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 WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Multiple Forms");
 WNDCLASSEX wc={};
 MSG messages;
 HWND hWnd;

 wc.lpszClassName=szClassName;                wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX);               wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 wc.hInstance=hInstance,                      wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW;    
 RegisterClassEx(&wc);
 hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,250,500,260,170,HWND_DESKTOP,0,hInstance,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
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
//Main.h
#ifndef MAIN_H
#define MAIN_H
#define dim(x)             (sizeof(x) / sizeof(x[0]))
#define IDC_BUTTON_FORM1   1600
#define IDC_BUTTON_FORM2   1605
#define IDC_BUTTON_FORM3   1610

typedef struct             WindowsEventArguments
{
 HWND                      hWnd;
 WPARAM                    wParam;
 LPARAM                    lParam;
 HINSTANCE                 hIns;
}WndEventArgs,             *lpWndEventArgs;

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

long fnWndProc_OnCreate    (lpWndEventArgs Wea);  //We need foreward declarations of
long fnWndProc_OnCommand   (lpWndEventArgs Wea);  //the various functions in a main
long fnWndProc_OnClose     (lpWndEventArgs Wea);  //header file so that the event
                                                  //handlers can be attached below.
long fnForm1_OnCreate      (lpWndEventArgs);
long fnForm1_OnPaint       (lpWndEventArgs);
long fnForm1_OnClose       (lpWndEventArgs);

long fnForm2_OnCreate      (lpWndEventArgs);
long fnForm2_OnPaint       (lpWndEventArgs);
long fnForm2_OnClose       (lpWndEventArgs);

long fnForm3_OnCreate      (lpWndEventArgs);
long fnForm3_OnPaint       (lpWndEventArgs);
long fnForm3_OnClose       (lpWndEventArgs);

const EVENTHANDLER         EventHandler[]=        //Since we foreward declared above
{                                                 //the various event handling functions
 {WM_CREATE,               fnWndProc_OnCreate},   //of the various forms, windows, dialogs
 {WM_COMMAND,              fnWndProc_OnCommand},  //above, we can fill out the fields of
 {WM_CLOSE,                fnWndProc_OnClose}     //our EVENTHANDLER structures for the
};                                                //various objects.

const EVENTHANDLER         Form1EventHandler[]=
{
 {WM_CREATE,               fnForm1_OnCreate},
 {WM_PAINT,                fnForm1_OnPaint},
 {WM_CLOSE,                fnForm1_OnClose}
};

const EVENTHANDLER         Form2EventHandler[]=
{
 {WM_CREATE,               fnForm2_OnCreate},
 {WM_PAINT,                fnForm2_OnPaint},
 {WM_CLOSE,                fnForm2_OnClose}
};

const EVENTHANDLER         Form3EventHandler[]=
{
 {WM_PAINT,                fnForm3_OnPaint},
 {WM_CLOSE,                fnForm3_OnClose}
};
#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
//Form1.cpp
#include  <Windows.h>
#include  <tchar.h>
#include  "Form1.h"
#include  "Main.h"


long fnForm1_OnCreate(lpWndEventArgs Wea)
{
 CREATESTRUCT *pCreateStruct;
 HWND hMain;

 pCreateStruct=(CREATESTRUCT*)Wea->lParam;
 hMain=(HWND)pCreateStruct->lpCreateParams;
 SetWindowLongPtr(Wea->hWnd,GWLP_USERDATA,(LONG_PTR)hMain);
 EnableWindow(hMain,FALSE);

 return 0;
}


long fnForm1_OnPaint(lpWndEventArgs Wea)
{
 PAINTSTRUCT ps;
 HDC hDC;

 hDC=BeginPaint(Wea->hWnd,&ps);
 TextOut(hDC,0,0,_T("This Is Form1.  It Disables The Main"),36);
 TextOut(hDC,0,16,_T("Window, And That Makes It Modal.  Note"),38);
 TextOut(hDC,0,32,_T("That We Passed The Handle Of The Main"),37);
 TextOut(hDC,0,48,_T("Window In The Last Parameter Of The"),35);
 TextOut(hDC,0,64,_T("CreateWindow() Call, And Retrieved It In"),40);
 TextOut(hDC,0,80,_T("fnForm1_OnCreate().  We Then Stored It So"),41);
 TextOut(hDC,0,96,_T("We Could EnableWindow(TRUE) The Main"),36);
 TextOut(hDC,0,112,_T("Window When This Modal Form Is"),30);
 TextOut(hDC,0,128,_T("Dismissed."),10);
 EndPaint(Wea->hWnd,&ps);

 return 0;
}


long fnForm1_OnClose(lpWndEventArgs Wea)
{
 HWND hMain;

 hMain=(HWND)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
 EnableWindow(hMain,TRUE);
 DestroyWindow(Wea->hWnd);
 return 0;
}


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

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

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


1
2
3
4
5
//Form1.h         //Needs to be included in Main.cpp because the WM_CREATE handler there
#ifndef FORM1_H   //references fnForm1_WndProc as the Window Procedure for the Form1 Class.
#define FORM1_H   //This would be needed to register the class.
LRESULT CALLBACK fnForm1_WndProc(HWND, unsigned int, WPARAM, LPARAM);
#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
//Form2.cpp
#include  <Windows.h>
#include  <tchar.h>
#include  "Main.h"
#include  "Form2.h"


long fnForm2_OnCreate(lpWndEventArgs Wea)
{
 CREATESTRUCT *pCreateStruct;
 HWND hMain;

 pCreateStruct=(CREATESTRUCT*)Wea->lParam;
 hMain=(HWND)pCreateStruct->lpCreateParams;
 SetWindowLongPtr(Wea->hWnd,GWLP_USERDATA,(LONG_PTR)hMain);
 ShowWindow(hMain,SW_HIDE);

 return 0;
}


long fnForm2_OnPaint(lpWndEventArgs Wea)
{
 PAINTSTRUCT ps;
 HDC hDC;

 hDC=BeginPaint(Wea->hWnd,&ps);
 TextOut(hDC,0,0,_T("This Is Form2.  It SW_HIDEs The Main"),36);
 TextOut(hDC,0,16,_T("Window, And SW_SHOWs It Upon Closing."),37);
 TextOut(hDC,0,32,_T("This Technique Can Be Used Similiarly"),37);
 TextOut(hDC,0,48,_T("To A Modal Dialog If It Isn't Necessary To"),42);
 TextOut(hDC,0,64,_T("View Simultaneously A Form Underneath The"),41);
 TextOut(hDC,0,80,_T("Dialog With Which You Can't Interact"),36);
 TextOut(hDC,0,96,_T("Anyway"),6);
 EndPaint(Wea->hWnd,&ps);

 return 0;
}


long fnForm2_OnClose(lpWndEventArgs Wea)
{
 HWND hMain;

 hMain=(HWND)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
 EnableWindow(hMain,TRUE);
 DestroyWindow(Wea->hWnd);
 ShowWindow(hMain,TRUE);

 return 0;
}


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

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

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


1
2
3
4
5
//Form2.h        //Needs to be included in Main.cpp because the WM_CREATE handler there
#ifndef FORM2_H  //references fnForm2_WndProc as the Window Procedure for the Form1 Class.
#define FORM2_H  //This would be needed to register the class.
LRESULT CALLBACK fnForm2_WndProc(HWND, unsigned int, WPARAM, LPARAM);
#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
//Form3.cpp
#include  <Windows.h>
#include  <tchar.h>
#include  "Main.h"
#include  "Form3.h"


long fnForm3_OnPaint(lpWndEventArgs Wea)
{
 PAINTSTRUCT ps;
 HDC hDC;

 hDC=BeginPaint(Wea->hWnd,&ps);
 TextOut(hDC,0,0,_T("This Is Form3.  Not Only Does It Neither"),40);
 TextOut(hDC,0,16,_T("Hide Nor Disable The Main Window, But"),37);
 TextOut(hDC,0,32,_T("You'll Find That You Can Create As Many"),39);
 TextOut(hDC,0,48,_T("Of These As You Like By Continually"),35);
 TextOut(hDC,0,64,_T("Clicking The Bottom Button On The Main"),38);
 TextOut(hDC,0,80,_T("Form.  However, You'll Have To Drag One"),39);
 TextOut(hDC,0,96,_T("From On Top Of The Other Because They"),37);
 TextOut(hDC,0,112,_T("All Appear In The Same Location (I"),34);
 TextOut(hDC,0,128,_T("Changed That).  You May Further Note"),36);
 TextOut(hDC,0,144,_T("That Since These Windows Are Neither"),36);
 TextOut(hDC,0,160,_T("Disabled Nor Hidden At Any Time, You"),36);
 TextOut(hDC,0,176,_T("May Interact With Them Irregardless Of"),38);
 TextOut(hDC,0,192,_T("The State Of Form1 Or Form2. Pretty"),35);
 TextOut(hDC,0,208,_T("Neat, Don't You Think?"),22);
 EndPaint(Wea->hWnd,&ps);

 return 0;
}


long fnForm3_OnClose(lpWndEventArgs Wea)
{
 HWND hMain;

 MessageBox
 (
  Wea->hWnd,
  _T("Good Way To Release Any Resources, Memory, etc., You May Have Allocated"),
  _T("Window Close Report!"),
  MB_OK
 );
 hMain=(HWND)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
 EnableWindow(hMain,TRUE);
 DestroyWindow(Wea->hWnd);
 ShowWindow(hMain,TRUE);

 return 0;
}


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

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

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


1
2
3
4
5
//Form3.h        //Needs to be included in Main.cpp because the WM_CREATE handler there
#ifndef FORM3_H  //references fnForm3_WndProc as the Window Procedure for the Form1 Class.
#define FORM3_H  //This would be needed to register the class.
LRESULT CALLBACK fnForm3_WndProc(HWND, unsigned int, WPARAM, LPARAM);
#endif 
Wow thank you guys so much for these responses! And thank you freddie!

Ill have to read this tomorrow I am exhausted right now
Topic archived. No new replies allowed.