Thread: Tabbed Dialog issue

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    I've got a dialog with a tab control. I fill each tab using a dialog resource. When I have another window in front of my app, clicking the blank space within the dialog (or any labels) won't bring it back to the top. It only becomes active again if I click on the title bar or a control (edit, combo box, anything). Any ideas why it would behave that way?

    some of the code that might be relevant:
    Code:
    DLG_RENEGADEX DIALOGEX 4,4,400,275
    CAPTION PROGRAM_NAME
    FONT 10,"MS Sans Serif",400,0,0
    STYLE WS_VISIBLE|WS_OVERLAPPEDWINDOW|DS_CENTER
    BEGIN
      CONTROL "",TAB_MAIN,"SysTabControl32",WS_CHILD|WS_VISIBLE|WS_TABSTOP|TCS_FOCUSNEVER,0,0,400,268
    END
    
    DLG_HOOK DIALOGEX MOVEABLE PURE LOADONCALL DISCARDABLE 5,5,396,262
    FONT 10,"MS Sans Serif",0,0,0
    STYLE 0x0004 | WS_CHILD
    BEGIN
      CONTROL "",LSV_HOOK_PROCESSES,"SysListView32",WS_CHILD|WS_VISIBLE|WS_TABSTOP|LVS_REPORT|LVS_SINGLESEL,7,24,143,218,WS_EX_CLIENTEDGE
      CONTROL "",CMB_HOOK_PRESETS,"ComboBox",WS_CHILD|WS_VISIBLE|WS_TABSTOP|CBS_HASSTRINGS|CBS_DROPDOWNLIST,226,27,117,137
    Code:
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    	LPSTR lpCmdLine, int nCmdShow)
    {
       INITCOMMONCONTROLSEX blah;
       blah.dwSize = sizeof(INITCOMMONCONTROLSEX);
       blah.dwICC = -1;
       InitCommonControlsEx(&blah);
       hinstMain = hInstance;
       hwndMain = CreateDialog(hInstance,MAKEINTRESOURCE(DLG_RENEGADEX),HWND_DESKTOP,MainProc);
       sprintf(ErrTxt, "%u", GetLastError());
       if (!hwndMain) { MessageBox(NULL,ErrTxt, "debug",MB_OK); }
    
       if (!hwndMain) return FALSE;
       ShowWindow(hwndMain, nCmdShow);
       UpdateWindow(hwndMain);
       MSG msg;
    //   HACCEL AccelMain = LoadAccelerators(hinstMain, "MainAccel");
       while(GetMessage(&msg, NULL, 0, 0))
       {
           //msg.hwnd could determine which procedure to translate accelerator for.
    //       if (!TranslateAccelerator(hwndMain, AccelMain, &msg)) {
               TranslateMessage(&msg);
               DispatchMessage(&msg);
    //       }
        }
       return (int)msg.wParam;
    }
    
    BOOL CALLBACK MainProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
        HWND hTabCtrl = GetDlgItem(hwnd, TAB_MAIN);
    
    	switch(Message)
    	{
    		case WM_INITDIALOG:
            {
                memset(&HookedProcess, 0, sizeof(PROCESS_INFORMATION));
                LoadSettings();
    		    InitTabControl(hwnd, lParam);
    		} break;
            case WM_NOTIFY:
            {
                NMHDR *hdr = (LPNMHDR)lParam;
                if (hdr->code == TCN_SELCHANGING || hdr->code == TCN_SELCHANGE)
                {
                    int index = TabCtrl_GetCurSel(hdr->hwndFrom);
                    if (index >= 0 && index < NUM_TABS) ShowWindow(hTabDlgs[index], (hdr->code == TCN_SELCHANGE) ? SW_SHOW : SW_HIDE);
                }
            } break;
    		case WM_CLOSE:
    		{
    //		    Free........();
                if (HookedProcess.hProcess) {
                    CloseHandle(HookedProcess.hProcess);
                    CloseHandle(HookedProcess.hThread);
                }
                DestroyWindow(hwnd);
    		} break;
    		case WM_DESTROY:
    		{
    			PostQuitMessage(0);
            } return 0;
    		default:
    			return FALSE;
    //		    return DefWindowProc(hwnd, Message, wParam, lParam);
    	}
    //	return 0;
        return DefWindowProc(hwnd, Message, wParam, lParam);
        //return 0 and default to DefWindowProc?
    }
    
    /***************************************************
    Tab control
    ****************************************************/
    int InitTabControl(HWND hwnd, LPARAM lParam)
    {
        TCITEM tabitem;
        HWND hTab;
    
        hTab = GetDlgItem(hwnd, TAB_MAIN);
        memset(&tabitem, 0, sizeof(tabitem));
    
        tabitem.mask = TCIF_TEXT;
    	tabitem.cchTextMax = MAX_PATH;
    
        tabitem.pszText = "Hook";
        SendMessage(hTab, TCM_INSERTITEM, HOOK_TAB, (LPARAM)&tabitem);
    
        tabitem.pszText = "Search";
        SendMessage(hTab, TCM_INSERTITEM, CODE_SEARCH_TAB, (LPARAM)&tabitem);
    
        tabitem.pszText = "Settings";
        SendMessage(hTab, TCM_INSERTITEM, SETTINGS_TAB, (LPARAM)&tabitem);
    
    	// Get the position that the dialogs should be displayed
    	RECT rt,itemrt;
    //	GetWindowRect(GetDlgItem(hwnd, LBL_TAB), &rt);
    	GetWindowRect(hTab, &rt);
        TabCtrl_GetItemRect(hTab,1,&itemrt);
        rt.top -= (itemrt.top - itemrt.bottom);
        rt.bottom -= rt.top;
        rt.right  -= rt.left;
    	ScreenToClient(hTab, (LPPOINT)&rt);
    
    	// Create the dialogs modelessly and move them appropriately
        hTabDlgs[HOOK_TAB] = CreateDialog((HINSTANCE)lParam, (LPSTR)DLG_HOOK, hTab, (DLGPROC)HookProc);
        hTabDlgs[CODE_SEARCH_TAB] = CreateDialog((HINSTANCE)lParam, (LPSTR)DLG_CODE_SEARCH, hTab, (DLGPROC)CodeSearchProc);
        hTabDlgs[SETTINGS_TAB] = CreateDialog((HINSTANCE)lParam, (LPSTR)DLG_SETTINGS, hTab, (DLGPROC)OptionsProc);
    
        MoveWindow(hTabDlgs[HOOK_TAB], rt.left, rt.top, rt.right, rt.bottom, 0);
        MoveWindow(hTabDlgs[CODE_SEARCH_TAB], rt.left, rt.top, rt.right, rt.bottom, 0);
        MoveWindow(hTabDlgs[SETTINGS_TAB], rt.left, rt.top, rt.right, rt.bottom, 0);
    
        // Show the default dialog
        ShowWindow(hTabDlgs[HOOK_TAB], SW_SHOW);
        return 0;
    }
    Last edited by Viper187; 10-04-2008 at 12:26 PM.

  2. #2
    Registered User
    Join Date
    Jul 2008
    Posts
    67
    Moin,

    I might be wrong, but I think you have to handle the DialogBox in a DialogProc, isn't it ?


    Greetz
    Greenhorn

  3. #3
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    yeah, so? every tab has it's own dialog procedure. There's nothing that should prevent the damn thing from restoring the window.

    Also, I thought the MainProc I posted above should be defaulting to DefWindowProc and returning 0 on what's handled, but it doesn't work right that way. The damn Close button ends up not working. ALT+F4 still does.

    Here's one of the tabs:
    Code:
    BOOL CALLBACK OptionsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        HWND hBaseDec = GetDlgItem(hwnd, OPT_SETT_DEC);
        HWND hBaseHex = GetDlgItem(hwnd, OPT_SETT_HEX);
        HWND hBaseFloat = GetDlgItem(hwnd, OPT_SETT_FLOAT);
        HWND hDumpDir = GetDlgItem(hwnd, TXT_SETT_DUMP_DIR);
    	switch(message)
    	{
    		case WM_INITDIALOG:
            {
                SendMessage(hBaseDec,BM_SETCHECK, (Settings.CS.NumBase == BASE_DEC) ? BST_CHECKED : BST_UNCHECKED,0);
                SendMessage(hBaseHex,BM_SETCHECK, (Settings.CS.NumBase == BASE_HEX) ? BST_CHECKED : BST_UNCHECKED,0);
                SetWindowText(hDumpDir, Settings.CS.DumpDir);
            } break;
    		case WM_COMMAND:
            {
    			switch(LOWORD(wParam))
                {
                    case OPT_SETT_DEC:
                    {
                        Settings.CS.NumBase = BASE_DEC;
    				} break;
                    case OPT_SETT_HEX:
                    {
                        Settings.CS.NumBase = BASE_HEX;
    				} break;
                    case OPT_SETT_FLOAT:
                    {
                        Settings.CS.NumBase = BASE_FLOAT;
    				} break;
    			    case CMD_SETT_DUMP_DIR:
    			    {
                        char DumpPath[MAX_PATH];
                        if (BrowseForFolder(hwnd, DumpPath)) {
                            strcpy(Settings.CS.DumpDir, DumpPath);
                            SetWindowText(hDumpDir, Settings.CS.DumpDir);
                        }
    			    } break;
                }
            } break;
    		default:
    		    return DefWindowProc(hwnd, message, wParam, lParam);
    	}
    	return FALSE;
    }
    Last edited by Viper187; 10-04-2008 at 11:16 AM.

  4. #4
    Registered User
    Join Date
    Jul 2008
    Posts
    67
    Hmm, it seems that you followed the examples of M$ for Tab Controls.
    I'm not so familiar with Dialogs, but this is what CodeBlocks gives me as Template (naturally without Tabs).

    resource.rc
    Code:
    // Generated by ResEdit 1.4.3
    // Copyright (C) 2006-2008
    // http://www.resedit.net
    
    #include "resource.h"
    #include <windows.h>
    
    
    //
    // Dialog resources
    //
    LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
    DLG_MAIN DIALOGEX 6, 5, 194, 106
    STYLE DS_3DLOOK | DS_CENTER | DS_SETFONT | WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_GROUP | WS_THICKFRAME | WS_SYSMENU
    CAPTION "Code::Blocks Template Dialog App"
    FONT 8, "MS Sans Serif", 0, 0, 1
    BEGIN
        PUSHBUTTON      "&Test", IDC_BTN_TEST, 138, 5, 46, 15
        PUSHBUTTON      "&Quit", IDC_BTN_QUIT, 138, 29, 46, 15
        CONTROL         "", IDC_TAB1, WC_TABCONTROL, 0, 4, 4, 125, 97
    END
    
    
    //
    // Manifest resources
    //
    LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
    1                  RT_MANIFEST    ".\\manifest.xml"
    main.cpp
    Code:
    #include "stdafx.h"
    #include "resource.h"
    
    HINSTANCE hInst;
    
    bool InitTabCtrl (HWND hTabWnd) {
    
    	TCITEM tie;
    
    	tie.mask    = TCIF_TEXT | TCIF_IMAGE;
    	tie.iImage  = -1;
    	tie.pszText = "1st";
    
    	TabCtrl_InsertItem (hTabWnd, TabCtrl_GetItemCount(hTabWnd), &tie);
    
    	tie.pszText = "2nd";
    
    	TabCtrl_InsertItem (hTabWnd, TabCtrl_GetItemCount(hTabWnd), &tie);
    
    	tie.pszText = "3rd";
    
    	TabCtrl_InsertItem (hTabWnd, TabCtrl_GetItemCount(hTabWnd), &tie);
    
    	tie.pszText = "4th";
    
    	TabCtrl_InsertItem (hTabWnd, TabCtrl_GetItemCount(hTabWnd), &tie);
    
    	return true;
    }
    
    BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	static HWND hwndTab;
    
        switch(uMsg)
        {
            case WM_INITDIALOG:
    
    			hwndTab = GetDlgItem (hwndDlg, IDC_TAB1);
    			InitTabCtrl (hwndTab);
    
    			/*
                 * TODO: Add code to initialize the dialog.
                 */
                return TRUE;
    
            case WM_CLOSE:
                EndDialog(hwndDlg, 0);
                return TRUE;
    
            case WM_COMMAND:
                switch(LOWORD(wParam))
                {
                    /*
                     * TODO: Add more control ID's, when needed.
                     */
                    case IDC_BTN_QUIT:
                        EndDialog(hwndDlg, 0);
                        return TRUE;
    
                    case IDC_BTN_TEST:
                        MessageBox(hwndDlg, "You clicked \"Test\" button!", "Information", MB_ICONINFORMATION);
                        return TRUE;
                }
        }
    
        return FALSE;
    }
    
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
        hInst = hInstance;
    
        INITCOMMONCONTROLSEX iccx;
    
        iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
        iccx.dwICC  = ICC_TAB_CLASSES | ICC_STANDARD_CLASSES;
    
        InitCommonControlsEx (&iccx);
    
        // The user interface is a modal dialog box
        return DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, DialogProc);
    }
    The return value of the DlgProc should be FALSE (or 0) and not DefWindowProc.
    DefWindowProc is used in window based applications and not in Dialog based applications.


    Greetz
    Greenhorn

  5. #5
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    Woah. That fixed it. Thanks! Are subclassed control procedures the same or different? The example I started from saved a pointer to the original and called it with CallWindowProc, and if it wasn't set called DefWindowProc. Calling the original procedure was actually in the MSDN example, if I remember right.
    Last edited by Viper187; 10-05-2008 at 07:40 AM.

  6. #6
    Registered User
    Join Date
    Jul 2008
    Posts
    67
    If you subclass a window using ComCtrl32.dll proir version 6, the default return should be a call of the origin window procedure, by using CallWindowProc (hOriginProc).
    Using ComCtrl32.dll version 6 makes another variant possible.

    http://msdn.microsoft.com/en-us/libr...83(VS.85).aspx



    Greetz
    Greenhorn

  7. #7
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    Ok. Too bad the damn thing doesn't list which version of the DLL is default with which version of Windows. That could be useful information, MAYBE.

  8. #8
    Registered User
    Join Date
    Jul 2008
    Posts
    67
    Hi,

    it is written on the webpage ...

    Subclassing Controls Using ComCtl32.dll version 6

    ComCtl32.dll version 6 supplied with Windows XP contains four functions that make creating subclasses easier and eliminate the disadvantages previously discussed. The new functions encapsulate the management involved with multiple sets of reference data, therefore the developer can focus on programming features and not on managing subclasses. The subclassing functions are:

    * SetWindowSubclass
    * GetWindowSubclass
    * RemoveWindowSubclass
    * DefSubclassProc
    So, set your "targetver.h" to this ...
    Code:
    #pragma once
    
    // Die folgenden Makros definieren die mindestens erforderliche Plattform. Die mindestens erforderliche Plattform
    // ist die früheste Windows-, Internet Explorer-Version usw., die über die erforderlichen Features zur Ausführung
    // Ihrer Anwendung verfügt. Die Makros aktivieren alle Funktionen, die auf den Plattformversionen bis
    // einschließlich der angegebenen Version verfügbar sind.
    
    // Ändern Sie folgende Definitionen für Plattformen, die älter als die unten angegebenen sind.
    // Unter MSDN finden Sie die neuesten Informationen über die entsprechenden Werte für die unterschiedlichen Plattformen.
    #pragma once
    
    #ifndef WINVER
    #define WINVER 0x0501
    #endif
    
    #ifndef _WIN32_WINNT
    #define _WIN32_WINNT 0x0501
    #endif
    
    #ifndef _WIN32_WINDOWS
    #define _WIN32_WINDOWS 0x0410
    #endif
    
    #ifndef _WIN32_IE
    #define _WIN32_IE 0x0600
    #endif
    This requires WinXP to run your application.


    Greetz
    Greenhorn

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Open dialog box issue
    By patrick22 in forum Windows Programming
    Replies: 6
    Last Post: 06-11-2008, 03:12 AM
  2. Replies: 9
    Last Post: 02-13-2008, 02:59 PM
  3. make Child Dialog not Popup?
    By Zeusbwr in forum Windows Programming
    Replies: 5
    Last Post: 04-08-2005, 02:42 PM
  4. Getting the position of a dialog without parent on the screen
    By stormbringer in forum Windows Programming
    Replies: 1
    Last Post: 08-27-2003, 02:59 AM
  5. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM