4

I'm having a problem in my program whenever I close the child window, the main window also exits.

I am a newbie in this programming.

The Correct Code:

 /**
    @file MainWindow.cpp
    @author Andro Bondoc
    @date 2011-02-11
 */

   /** @file MainWindow.cpp @author Andro Bondoc @date 2011-02-11 */

#include "tray.h"



#define WM_USER_SHELLICON WM_USER + 1 

HWND hWnd, Button, LoadNew, TextBox;
HINSTANCE hInst;
HICON hMainIcon;
HMENU hPopMenu;
NOTIFYICONDATA structNID;

long PASCAL WndProcParent(HWND,UINT,UINT,LONG);
long PASCAL WndProcChild(HWND,UINT,UINT,LONG);


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{

    MSG msg;
    WNDCLASS wc, ws;

    hInst = hInstance;
    if(!hPrevInstance)
    {
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WndProcParent;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(hInstance,(LPCTSTR)MAKEINTRESOURCE(IDI_TRAYICON));//LoadIcon(NULL,IDI_APPLICATION);
        wc.hCursor = LoadCursor(NULL,IDC_ARROW);
        wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
        wc.lpszMenuName = NULL;
        wc.lpszClassName = "Data Retriever Parent";
        RegisterClass(&wc);

        ws.style = CS_HREDRAW | CS_VREDRAW;
        ws.lpfnWndProc = WndProcChild;
        ws.cbClsExtra = 0;
        ws.cbWndExtra = 0;
        ws.hInstance = hInstance;
        ws.hIcon = LoadIcon(hInstance,(LPCTSTR)MAKEINTRESOURCE(IDI_TRAYICON));//LoadIcon(NULL,IDI_APPLICATION);
        ws.hCursor = LoadCursor(NULL,IDC_ARROW);
        ws.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
        ws.lpszMenuName = NULL;
        ws.lpszClassName = "Data Retriever Child";
        RegisterClass(&ws);
    }

            hWnd = CreateWindowEx(0, wc.lpszClassName, "Data Retriever",
                       WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       NULL, NULL, hInstance, NULL);

            LoadNew = CreateWindowEx(0, ws.lpszClassName, "Help Program",
                       WS_BORDER | WS_CAPTION | WS_CHILD,
                       120,
                       80,
                       500,
                       300,
                       hWnd, NULL, hInstance, NULL);




    hMainIcon = LoadIcon(hInstance,(LPCTSTR)MAKEINTRESOURCE(IDI_TRAYICON)); 


    structNID.cbSize = sizeof(NOTIFYICONDATA);
    structNID.hWnd = (HWND) hWnd; 
    structNID.uID = IDI_TRAYICON; 
    structNID.uFlags = NIF_ICON | NIF_MESSAGE; 
    structNID.hIcon = hMainIcon; 
    structNID.uCallbackMessage = WM_USER_SHELLICON; 


    Shell_NotifyIcon(NIM_ADD, &structNID); 

    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}



long FAR PASCAL WndProcParent(HWND hwnd,UINT message,UINT wParam,long lParam)
{
   HDC hdc = NULL;
   POINT lpClickPoint;
   char buff[100] = "";

        switch(message){
                case WM_CREATE:

                Button = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Close",
                WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 680,480, 80, 30, hwnd, (HMENU)ID_CLOSE,
                GetModuleHandle(NULL), NULL);

                Button = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Help",
                WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 680,450, 80, 30, hwnd, (HMENU)ID_HELPDAW,
                GetModuleHandle(NULL), NULL);

                break;


        /*case WM_DESTROY:

                PostQuitMessage(0);
                return 0;*/

        case WM_USER_SHELLICON: 

            switch(LOWORD(lParam)) 
            { 
                case WM_LBUTTONDBLCLK: 
                    ShowWindow(hwnd, SW_RESTORE);
                    break;

                case WM_RBUTTONDOWN: 
                    //get mouse cursor position x and y as lParam has the message itself 
                    GetCursorPos(&lpClickPoint);

                    //place the window/menu there if needed 

                    hPopMenu = CreatePopupMenu();
                    InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,ID_OPEN,"&Open");
                    InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,ID_HELPDAW,"&Help");
                    InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,ID_CLOSE,"&Exit");

                        //workaround for microsoft bug, to hide menu w/o selecting
                    SetForegroundWindow(hWnd);
                    TrackPopupMenu(hPopMenu,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_BOTTOMALIGN,lpClickPoint.x, lpClickPoint.y,0,hWnd,NULL);
                    SendMessage(hWnd,WM_NULL,0,0);

                    //MessageBox(NULL,"TEST rightclick","Testing ...",MB_OK); 

                    return TRUE; 
            }

            break; 

        case WM_COMMAND: 

            if(ID_CLOSE == LOWORD(wParam))
            {
                int iRes = MessageBox(NULL,"Do you want to Exit","Data Retriever",MB_YESNO|MB_ICONQUESTION);
                if(IDYES == iRes)
                {
                Shell_NotifyIcon(NIM_DELETE,&structNID);
                DestroyWindow(hWnd);
                PostQuitMessage(0);
                }

            }
            else if(ID_HELPDAW == LOWORD(wParam))
            {
                ShowWindow(LoadNew, SW_SHOW);
                //MessageBox(NULL, "Help","Data Retriever",MB_OK|MB_ICONQUESTION);                      
            }

            else if(ID_OPEN == LOWORD(wParam))
            {
                ShowWindow(hWnd, SW_NORMAL); 
            }
            break;

        case WM_CLOSE: 

                Shell_NotifyIcon(NIM_DELETE,&structNID);
                DestroyWindow(hWnd);
                PostQuitMessage(0);

            break;

        case WM_SYSCOMMAND: 

            if(SC_MINIMIZE == wParam) 
            { 
                ShowWindow(hWnd,SW_HIDE);
                return TRUE; 
            }
            break;

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

long FAR PASCAL WndProcChild(HWND hwnd,UINT message,UINT wParam,long lParam){
   HDC hdc = NULL;
   PAINTSTRUCT ps;
   char buff[100] = "";
   switch(message){
                case WM_CREATE:

                Button = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Unload",
                WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 20,20, 80, 30, hwnd, (HMENU)ID_MESSAGE,
                GetModuleHandle(NULL), NULL);


                break;


        case WM_COMMAND: 


            if(ID_RETURN == LOWORD(wParam))
            {
                ShowWindow(hWnd, SW_SHOW);
                ShowWindow(LoadNew,SW_HIDE);
                //MessageBox(NULL, "Help","Data Retriever",MB_OK|MB_ICONQUESTION);                      
            }


        case WM_CLOSE: 

            ShowWindow(hWnd, SW_SHOW);
            ShowWindow(LoadNew,SW_HIDE);
            break;

        case WM_PAINT:

            RECT rect;

            GetClientRect(LoadNew,&rect);
            hdc = BeginPaint(LoadNew,&ps);

            strcpy_s(buff,"TOP");
            DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_CENTER|DT_TOP);
            strcpy_s(buff,"RIGHT");
            DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_VCENTER|DT_RIGHT);
            strcpy_s(buff,"BOTTOM");
            DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_CENTER|DT_BOTTOM);
            strcpy_s(buff,"LEFT");
            DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);
            strcpy_s(buff,"CENTER");
            DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
            strcpy_s(buff,"BOTTOM-LEFT");
            DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_BOTTOM|DT_LEFT);
            strcpy_s(buff,"BOTTOM-RIGHT");
            DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_BOTTOM|DT_RIGHT);
            strcpy_s(buff,"TOP-LEFT");
            DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_TOP|DT_LEFT);
            strcpy_s(buff,"TOP-RIGHT");
            DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_TOP|DT_RIGHT);

            EndPaint(LoadNew,&ps);
            break;
        }
return DefWindowProc(hwnd,message,wParam,lParam);
}
  • You'll have to provide more details. Source code would be helpful. – Maxpm Feb 15 '11 at 05:26
  • Also, which OS and framework are you using? – Marcelo Cantos Feb 15 '11 at 05:28
  • I assume you're writing a program targeting the Win32 API? Please post the relevant sections of your code. For starters, where you *create* and *close* the child window. – Cody Gray Feb 15 '11 at 05:30
  • Best if you edit your original question to post the code. Comments don't allow multiple lines, or have any kind of syntax highlighting. Use the edit hyperlink underneath the tags. – Cody Gray Feb 15 '11 at 05:32

2 Answers2

5

You have the same wndproc code for each window. For WM_CLOSE, you DestroyWindow(hWnd), where hWnd is the global that stores your main window.

So, closing your child window closes the main window because you told it to.

Michael
  • 51,314
  • 5
  • 111
  • 139
  • 4
    First, you should create separate wndprocs - I doubt 100% of the main window behavior is applicable to the child window, and so on. In general, in the wnd proc for the child there shouldn't be any manipulations of the parent window. – Michael Feb 15 '11 at 05:45
  • If i will create a new wndprocs, would it be the same if i will call the child window then>? – Andro Miguel M. Bondoc Feb 15 '11 at 05:49
  • I created a new wndProcs but I got an Error. This is the ERROR: function 'long WndProc(HWND,UINT,UINT,LONG)' already has a body – Andro Miguel M. Bondoc Feb 15 '11 at 06:06
  • 1
    @Andro: Give them different names, e.g. `WndProcParent` and `WndProcChild`. The function name doesn't matter, all that matters is that you set the value of `lpfnWndProc` in the `WNDCLASS` structure to point to your appropriate window procedure—note that you will need to register two window classes, one for the parent, and one for the child. – Adam Rosenfield Feb 15 '11 at 06:09
  • @Micheal - i seperated wndProcs but still it exits the main window – Andro Miguel M. Bondoc Feb 15 '11 at 06:31
  • Did you update the call to Destroy(hWnd) in the WM_CLOSE of your child window? – Michael Feb 15 '11 at 17:15
  • @Andro: You didn't follow *all* of the advice. You separated the window procedures, but you're still registering the class with only one (`WndProcParent`), so the child events are still getting routed through the *parent's* window procedure. As Michael mentioned, you need to register *two* window classes, one for the parent and one for the child, and assign the `WndProc` functions accordingly. (Also, you really should be compiling new code as Unicode—check your compiler settings. Without modification, this code won't compile as Unicode.) – Cody Gray Feb 16 '11 at 00:26
  • @Cody Gray - I had registered the two WndProcs. But whenever I close the child window it still destroys the parent window but its still runs the program even the windows are gone already. – Andro Miguel M. Bondoc Feb 16 '11 at 01:16
2

Your modified code is still using the same WndProc for both windows. You tried to call RegisterClass twice with the same class name. The WndProcs will not be separated until you change the name.

ws.lpszClassName = "Data Retriever CHILD";

This problem would have been more readily apparent if you had checked the return value from RegisterClass - currently, the second call fails. There's other problems with this code (the MessageBox call in the child WndProc is really obnoxious, for example), but this change should be enough to get you headed in the right direction.

Jon
  • 2,982
  • 1
  • 18
  • 26