Thread: open multiple windows

  1. #1
    Registered User
    Join Date
    Sep 2010
    Posts
    69

    open multiple windows

    Hey guys,
    I'm having a bit of difficulty getting a handle on a concept I'm working on.

    First let me preface by saying that I'm experienced at C programming (not C++). Mainly Console Mode (not GUI) programming. So, when it comes to Windows GUI programming I'm a complete novice.

    What I would like to do is a bit different from the usual Windows GUI app, where to open a window you have a WinMain() followed up by a WinProc() for that window to handle callbacks.
    The usual one for one, if you will, (one WinMain -> one window -> one WinProc).

    What I'd like to do is have a generic "WinMain" type of function for registering a single WNDCLASS and a generic "WinProc" template for handling callbacks for subsequent windows opened using the already registered WNDCLASS.

    I can register a WNDCLASS and using the same lpszClassName parameter and open multiple windows, using different MenuNames.
    Like:
    Code:
        wndClass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
        wndClass.lpfnWndProc   = WndProc;
        wndClass.hInstance     = hInstance;
        wndClass.hCursor       = LoadCursor(hInstance, IDC_ARROW);
        wndClass.hIcon         = LoadIcon(hInstance, IDI_APPLICATION);
        wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wndClass.lpszClassName = szAppName;
    
        RegisterClass(&wndClass)
    followed by:
    Code:
       hwnd1 = CreateWindow(szAppName, "MyWindow1", ...,);
    and later, followed by:
    Code:
       hwnd2 = CreateWindow(szAppName, "MyWindow2", ...,);
    This displays two windows.
    However, when I close either one of the windows, it closes both windows.
    Clearly I'm missing something here.

    The Platform SDK suggests (or at least that's my impression) that it can be done, but, I haven't found the right example to understand how to make it work.

    From SDK:
    Each window class has an associated window procedure shared by all windows of the same class. The window procedure processes messages for all windows of that class and therefore controls their behavior and appearance.
    Maybe someone here understands how to do this.

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Usually a program will have one main window, then sub-windows are dialogs which are usually created using a resource editor. Each dialog has it's own dailogproc, so no conflicts.

    In the case of multiple "top level" windows, you should register multiple classes and give each one it's own message tosser (wndproc()).

    All windows in your program should share a common message dispatcher loop...

    Code:
        // dispatch window messages
        while (GetMessage(&msg,NULL,0,0) > 0)
          if (!TranslateAccelerator(GetForegroundWindow(),AccelTable,&msg))
           if(!IsDialogMessage(GetForegroundWindow(),&msg))
             { TranslateMessage(&msg);
               DispatchMessage(&msg); }
    It is possible --although terribly convoluted-- for two windows to share a tosser... but every case statement (eg. case: WM_CLOSE) and all functions accessed from those statements will have to be made sensitive to the window's handle. It's just a lot simpler to have two classes and two tossers.
    Last edited by CommonTater; 02-16-2011 at 02:24 PM.

  3. #3
    Registered User
    Join Date
    Sep 2010
    Posts
    69
    Thanks Tater,
    Perhaps my approach is wrong.
    The program begins in a Console Mode window, which then opens up secondary GUI windows.
    Perhaps instead of the approach I'm using, as you suggest, I should be opening Dialogs. I had not considered that.
    I'll look into that.

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    While you can open dialogs and sub-windows from a console, this too is somewhat less than optimal behaviour... It's generally wise to do it all one way or all the other... It keeps the code simpler and you can use windows controls (which are windows in themselves) far more effectively than you will ever use a console.

    You may also want to read up on the old-style MDI windows... windows opened inside a main window... but with some special logic to keep everything making sense.

    May I ask what it is you're trying to get working?
    Last edited by CommonTater; 02-16-2011 at 02:52 PM.

  5. #5
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    You're probably calling PostQuitMessage from WM_DESTROY so that when either window is closed your whole app is terminated.

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Steve A. View Post
    The Platform SDK suggests (or at least that's my impression) that it can be done, but, I haven't found the right example to understand how to make it work.
    The SDK's description is a bit misleading. I'm sure they mean sub-windows in the same class... that is a parent with it's children as opposed to multiple parent windows.

  7. #7
    Registered User
    Join Date
    Sep 2010
    Posts
    69
    May I ask what it is you're trying to get working?
    It's actually a Basic-like interpreter.
    It works quite well actually, I want to add functionality to it.
    It currently functions in Console Mode and I want to add Native GUI capability.

  8. #8
    Registered User
    Join Date
    Sep 2010
    Posts
    69
    You're probably calling PostQuitMessage from WM_DESTROY so that when either window is closed your whole app is terminated.
    Yes, I didn't know there was any other way.
    How else might I do that.

  9. #9
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Keep a count of how many windows you create, when you're destroying the last one call PostQuitMessage. There's no problem with creating multiple top-level windows, here's my WindowWatcher doing it. Don't click the link in the description, it doesn't work
    Last edited by adeyblue; 02-16-2011 at 03:41 PM.

  10. #10
    Registered User
    Join Date
    Sep 2010
    Posts
    69
    Quote Originally Posted by adeyblue View Post
    Keep a count of how many windows you create, when you're destroying the last one call PostQuitMessage.
    Ahhhh!
    I get it.
    Btw, I was keeping count, but, for another reason. Now it makes sense.
    Huh!

  11. #11
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Steve A. View Post
    Ahhhh!
    I get it.
    Btw, I was keeping count, but, for another reason. Now it makes sense.
    Huh!
    Window Watcher is pretty cool...

    But it's not the same as having multiple top level windows open *in the same application*...

    In the demo video, he has multiple applications open --MS Word, Browser, Media Player-- being monitored by yet another application (his)... Thus everything is running it's own classes and tossers.

    Take the example of a simple message... WM_SIZE... Ok, now you have 3 windows open with different controls in each window. If you resize one of them the system sends WM_SIZE, now it's not going to know which window to redraw... To fix this you have to track the foreground window and make WM_SIZE sensitive to the window handle... The same will apply to WM_CLOSE, WM_PAINT, WM_CHAR, etc. And that's a lot of complex coding that just begs errors.

    On the other hand making separate classes for each top level window and working them off separate tossers... no problem, the dispatcher I showed you earlier will sort that all out for you automatically.

    It's also likely that will turn into a bigger fiasco when you have client programmers writing their own code, making their own windows and dialogs, so unless you're planning some serious obfuscation of the underlying mechanisms, it's going to be a real pain for both you and them.

  12. #12
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Steve A. View Post
    Yes, I didn't know there was any other way.
    How else might I do that.
    There really isn't any other way. Check the SDK... the shut down for an app is to catch WM_CLOSE, do whatever you need to save data and shut down processes, then when WM_CLOSE returns the system immediately sends WM_DESTROY where you are supposed to shut down the dispatcher, which then falls through to WinMain() and causes the application to exit.

    You can sensitize that so only one of your windows can cause a program exit, but it's going to depend on the application which window that is... you can't always exit when the last window is closed... you want to exit when the *main* window is closed.

    Silly as it sounds... there are rules about this, set down my Microsoft as a means of providing a uniform end user experience in Windows.

  13. #13
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Quote Originally Posted by CommonTater View Post
    In the demo video, he has multiple applications open --MS Word, Browser, Media Player-- being monitored by yet another application (his)... Thus everything is running it's own classes and tossers.
    WindowWatcher has one message pump, one window class and one wndproc, and the demo is running two top-level windows (that's top-level in the WinAPI sense, unowned desktop parented windows). That's what I meant.

    If you and the OP meant something like MDI then, sshh, I'm learning how to spam.

    There really isn't any other way.
    I don't know. A thread timer that periodically calls EnumThreadWindows and exits the app if it finds none would work. You could also use a thread per window approach, with the main thread waiting for them all to exit. You wouldn't even have to remove the PostQuitMessage with that approach. But yeah, that's just being pedantic, nobody would ever do any of that, would they? We should start an experiment with the most contrived code possible and see how many copy 'n paste people run with it
    Last edited by adeyblue; 02-16-2011 at 06:04 PM. Reason: Needed more words

  14. #14
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by adeyblue View Post
    WindowWatcher has one message pump, one window class and one wndproc, and the demo is running two top-level windows (that's top-level in the WinAPI sense, unowned desktop parented windows). That's what I meant.
    That was not apparent from the video...

  15. #15
    Registered User
    Join Date
    Sep 2010
    Posts
    69
    Hey Guys,
    okay, still learning...,

    let's assume I open a single gui window and draw some text on it via WM_PAINT, (which is in my wndproc() function), like below:

    Code:
            case WM_PAINT:
                BeginPaint(hwnd, &ps);
    
                GetClientRect(hwnd, &rect);
                DrawText(hdc, "Hello World!.", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    
                EndPaint(hwnd, &ps);
                break;
    then, else where, (in another function) I issue a gdi line-draw command like so:
    Code:
    void DrawLine(HWND hwnd)
    {
        int x1=50, y1=50, x2=50, y2=150;
        HDC  myhDC;
    
        myhDC = GetDC(hwnd);
    
        MoveToEx(myhDC, x1, y1, NULL);
        LineTo(myhDC, x2, y2);
    
        ReleaseDC(hwnd, myhDC);
    }
    In the center of my window I have text that reads "Hello World!" and near the upper left corner, I have a 100 pixels long line.
    I can drag my window all over the screen and my two objects remain in tact.
    However, if I cover my window with another window, only the text remains when I toggle back to my window. The gdi line is no longer displayed.

    How would I get windows to redraw the entire contents of the window, including the gdi line I have drawn ?
    (without putting the line-draw routine inside of WM_PAINT, that is).
    Last edited by Steve A.; 02-22-2011 at 07:59 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Windows File open permisisons
    By somekid413 in forum C Programming
    Replies: 2
    Last Post: 10-18-2010, 01:24 PM
  2. Memory Leak in AppWizard-Generated Code
    By jrohde in forum Windows Programming
    Replies: 4
    Last Post: 05-19-2010, 04:24 PM
  3. Multiple Windows
    By napalm in forum C Programming
    Replies: 5
    Last Post: 04-25-2008, 04:02 AM
  4. IE 6 status bar
    By DavidP in forum Tech Board
    Replies: 15
    Last Post: 10-23-2002, 05:31 PM
  5. Multiple Windows, One Program?
    By skyruler54 in forum C++ Programming
    Replies: 3
    Last Post: 10-12-2002, 08:29 PM