Making multiple windows in a program?

Probably will be posting more frequently on this now, because now I am officially bored of console applications... and am trying to learn windows API

I am a windows.h noob, and I can make buttons that do stuff, display static text, make a textfield (cant store stuff in it), but I want to make a window pop up when I click a button, like, a separate window not a messagebox (been doing that for a while).
Anyway, here's what I got so far:

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
#include <windows.h>

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "CodeBlocksWindowsApp";

HWND button;

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Code::Blocks Template Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

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;
        case WM_CREATE:
            button = CreateWindow("BUTTON",
                                  "CLICK ME",
                                  WS_VISIBLE | WS_BORDER | WS_CHILD,
                                  100, 50, 75, 30,
                                  hwnd, (HMENU)1, NULL, NULL);

            break;
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case 1:
                    
                    break;
            }

            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}
Last edited on
If you want a modal dialog (something like MessageBox does) use DialogBox API:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645452%28v=vs.85%29.aspx

It requires its own window procedure called DialogProc which you must write.
Ok, I know this might sound pathetic, but I have tried the microsoft help site... I hate it, haha. I can't find anything I am looking for in it, nor figure out how to read the tutorials (What is _In_opt_ mean?). Could you just like, give me a heads up on how? That would be EXtremely helpful.

Please note that I am a beginner in windows (if it even is windows.h, I may just b being stupid), so this is why I don't get what that is.
I've always hated the default Win32 Winodow from Code::Blocks. The comment in Line 23 should more accurately read "The OS calls this function to process messages sent to this instance of the WNDCLASSEX class". Line 61 is especially stupid because the variable that should go in for the second argument to "GetMessage()" was used just three lines above it. I don't care if it seems verbose, people learn things wrong because of stupid oversights like this.


@ OP: Lines 18 - 55 are what you need to create an instance of a Window and register it with the OS. If you haven't tried to write your own wrapper class to do this stuff automatically yet then do so now. In most cases each Window should have it's own thread to process it's own message queue but they should also know to close when their parent Window does.

EDIT: To answer your question, _In_Opt_ means "Input Optional". It is not required to be a valid variable and passing NULL is acceptable behavior.
Last edited on
OMG thank you, about the _In_opt_ thing. That clears up SO MUCH for me. I thought it was some function you had to call, and I was thinking, "Where do I create that?"

And you are really right about the Code::Blocks thing. I didn't really want it to do it for me, but it did and I was like, ok, whatever, I will go on with it on, which is the worst thing a programmer could do because you dont learn anything.

Oh, and since I don't really like Code::Blocks (answer this if you want), but is there another IDE? Eclipse C++ doesn't work with windows 8 and I hate Dev C++'s old UI. Is there another IDE I could use? There is visual studio, but that is like, 400 dollars last time I checked.
I actually use Code::Blocks, the IDE itself isn't bad and the price is perfect for it. I just never liked this particular part of it, I don't really have any complaints about anything else.
There is visual studio, but that is like, 400 dollars last time I checked.


Express Edition is FREE.
Exactly what you are looking for is in Reply #5 at this link ...

A Project Concentrating On Creating Multiple Forms
http://www.jose.it-berater.org/smfforum/index.php?topic=3392.0

There is a main form with three buttons on it. Each button click creates another form/dialog/window of a different type (one is a moday dialog, another hides the main window untill you dismiss it, and the 3rd is just another window that can be created each time a button is clicked). I would say it is a good learning app, but it will be difficult for you. If you have difficulties I will help you though.

It is hard to get started in Windows Api coding, as you've found out. You have lots of questions and are able to find answers to everything but what you want. Its really good to start with a tutorial or book that will take you in the direction you wnt to go.
Last edited on
I like Code::Blocks too. I have the expensive version of VStudio, but mostly use C:B.

In most cases each Window should have it's own thread to process it's own message queue but they should also know to close when their parent Window does.


I don't know that I'd agree with that Computergeek. I've never found it necessary to create a seperate thread for each window. Where I find multi-threading useful is for prolonged tasks a GUI element might get involved with, i.e., worker threads.

I think the fundamental idea to multi-windowed applications derives directly from fundamental OOP principals, and that is that objects do seperate encapsulated sorts of things. If you have an application that does three seperate things then you might need three objects. If you need multiple forms/windows/dialogs, then you have an application that does multiple things. It stands to reason that there may be three 'classes' of objects - each requiring a seperate window. In SDK Style API coding that is going to translate into three Window Classes - each with its own Window Procedure do deal specifically with issues having to do with instantiations of objects of that class.

So then think about where you might want to put registration code for additional Window Classes. I prefer to put mine in WM_CREATE handlers of my main program window. Further realize that every registered Window Class needs its own Window Procedure. This is also in keeping with the ideas of OOP, in that, for example, each specific Window Procedure will only get messages related to that specific window and relating to whatever task that window has in the grand scheme of things.

Then think about making a multiple file C++ project where each specific form/window/dialog has its own *.cpp and *.h files. That project I gave a lint to above shows that.
@ freddie1: Either that second paragraph isn't an argument for why you disagree with me about the thread thing, or you went off on a bit of tangent. I'm not saying you're wrong; you can just as easily have an array of Window objects and just loop through them while calling the "Get\Translate\DispatchMessage()" functions. Adding threads might be more complexity then is necessary depending on the project. I just don't see a reason why threads A and B need to wait while thread C is searching\saving\downloading a large file or whatever else. This is a design consideration.
Topic archived. No new replies allowed.