PropertySheet redraw problem

Hello,

I am writing an Microsoft Outlook extension in the form of a C++ / Win32 API DLL.  The extension DLL has the ability to display a property sheet using the Win32 API function PropertySheet().

My property dialog displays fine and I am able to load the property sheet when first displayed, and store any modified controls when the user clicks 'OK'.  Great!

But I still have a problem.  Neither Outlook, the application that calls by DLL function nor my DLL's property sheet dialog redraw themselves.  If I move the dialog around over the Outlook window, the parts that had been covered by the dialog are not redrawn.  Also the dialog itself does not redraw, except for the edit controls and buttons when you click on them.

I have never used PropertySheet() or done Win32 API GUIs before, so I do not know if I am handling all the events I should.  Should I be handling WM_PAINT?  Am I missing some event or property sheet option / flag?

Any help or clues would be greatly appreciated.

The full source of my function can be found at
http://cvs.sourceforge.net/viewcvs.py/otlkcon/otlkcon0/otlkcon_gui.cpp?view=markup

Except follows....

STDMETHODIMP otlkcon_config::showGui()
{
    HRESULT result       = S_OK;
    PROPSHEETPAGE psp[2] = {0};
    PROPSHEETHEADER psh  = {0};
    HMODULE hMod         = 0;
   
    hMod = GetModuleHandleW(OTLKCON_MSTORE_DLL_NAME);

    // Property Sheet Header
    psh.dwSize      = sizeof(PROPSHEETHEADER);
    psh.dwFlags     = PSH_PROPSHEETPAGE;
    psh.hwndParent  = ulUIParam;
    psh.hInstance   = hMod;
    //  psh.pszIcon =
    //       MAKEINTRESOURCE(IDI_CELL_PROPERTIES);
    // psh.pszCaption    = (LPSTR) "Cell Properties";
    psh.nPages           = 2;//sizeof(psp) / sizeof(PROPSHEETPAGE);
    psh.nStartPage       = 0;
    psh.ppsp             = (LPCPROPSHEETPAGE) &psp;
    psh.pfnCallback      = NULL;//(PFNPROPSHEETCALLBACK)otlkcon_sheetCallback;

    // First Page
    psp[0].dwSize        = sizeof(PROPSHEETPAGE);
    psp[0].dwFlags       = PSP_USECALLBACK; //PSP_USEICONID | PSP_USETITLE;
    //psp[0].hInstance   = NULL;
    psp[0].pszTemplate   = MAKEINTRESOURCE(IDD_GENERALPAGE);
    //psp[0].pszIcon     = MAKEINTRESOURCE(IDI_FONT);
    psp[0].pfnDlgProc    = (DLGPROC)otlkcon_sheet1DlgProc;
    psp[0].lParam        = (LPARAM)this;
    psp[0].pszTitle      = "General Page";
    psp[0].pfnCallback   = otlkcon_sheetCallback;
    psp[0].hInstance     = hMod;

    // Second Page
    psp[1].dwSize        = sizeof(PROPSHEETPAGE);
    psp[1].dwFlags       = PSP_USECALLBACK; //PSP_USEICONID | PSP_USETITLE;
    //psp[1].hInstance   = NULL;
    psp[1].pszTemplate   = MAKEINTRESOURCE(IDD_DEBUGPAGE);
    //psp[1].pszIcon     = MAKEINTRESOURCE(IDI_FONT);
    psp[1].pfnDlgProc    = (DLGPROC)otlkcon_sheet2DlgProc;
    psp[1].lParam        = (LPARAM)this;
    psp[1].pszTitle      = "Debug Page";
    psp[1].pfnCallback   = otlkcon_sheetCallback;
    psp[1].hInstance     = hMod;

    // Show the sheets
    INT_PTR ret = PropertySheet(&psh);

    return result;
}

INT_PTR CALLBACK otlkcon_sheet1DlgProc(HWND hwnd, UINT uMsg, WPARAM wparam, LPARAM lparam )
{
    INT_PTR result = 0;
    HRESULT res = S_OK;
    otlkcon_config *conf = NULL;
    LPPROPSHEETPAGE sheet;
    wchar_t *tmpDbFilename = NULL;
    bool tmpXPEnable = false;

    sheet = (LPPROPSHEETPAGE)lparam;

    switch (uMsg)
    {
          case WM_INITDIALOG:
            if( sheet )
            {
                conf = (otlkcon_config *)sheet->lParam;
                tmpDbFilename = wcsdup( conf->dbFilename.c_str() );
                tmpXPEnable   = conf->xpEnabled;
            }
           
            SetWindowLong(hwnd, GWL_USERDATA, (LONG)conf);

            // PR_PST_PATH
            if( tmpDbFilename
                    && (SetDlgItemTextW(hwnd, IDC_DATAFILE_EDIT, tmpDbFilename) == 0) )
            {
                OTLKCON_LOG_PRINT_LAST_ERROR();
            }

            // PR_OTLKCON_XP_ENABLED
            if( CheckDlgButton(hwnd, IDC_ENABLE_XPP_CHECK,
                                tmpXPEnable?BST_CHECKED:BST_UNCHECKED) == 0 )
            {
                OTLKCON_LOG_PRINT_LAST_ERROR();
            }

            return TRUE;

        case WM_NOTIFY:
            switch (((NMHDR*)lparam)->code)
            {
                case PSN_APPLY:
                    conf = (otlkcon_config *)GetWindowLong(hwnd, GWL_USERDATA);
                    tmpDbFilename = (wchar_t *)calloc(1, (MAX_PATH+1)*sizeof(wchar_t));

                    // PR_PST_PATH
                    if( GetDlgItemTextW(hwnd, IDC_DATAFILE_EDIT, tmpDbFilename, MAX_PATH)
                                                == 0 )
                    {
                        OTLKCON_LOG_PRINT_LAST_ERROR();
                    }
                    conf->dbFilename = tmpDbFilename;

                    // PR_OTLKCON_XP_ENABLED
                    if( IsDlgButtonChecked(hwnd, IDC_ENABLE_XPP_CHECK )
                                                            == BST_CHECKED )
                    {
                        conf->xpEnabled = true;
                    }
                    else
                    {
                        conf->xpEnabled = false;
                    }
                    return FALSE;
            }
            return FALSE;
    }
    return TRUE;
}
k3rv1nAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
All you need to do to achieve that is that you add a call to 'DefDlgProc()' in the 'default:' handler of  'otlkcon_sheet1DlgProc()':

INT_PTR CALLBACK otlkcon_sheet1DlgProc(HWND hwnd, UINT uMsg, WPARAM wparam, LPARAM lparam )
{
    INT_PTR result = 0;
    HRESULT res = S_OK;
    otlkcon_config *conf = NULL;
    LPPROPSHEETPAGE sheet;
    wchar_t *tmpDbFilename = NULL;
    bool tmpXPEnable = false;

    sheet = (LPPROPSHEETPAGE)lparam;

    switch (uMsg)
    {
         case WM_INITDIALOG:
            if( sheet )
            {
                conf = (otlkcon_config *)sheet->lParam;
                tmpDbFilename = wcsdup( conf->dbFilename.c_str() );
                tmpXPEnable   = conf->xpEnabled;
            }
           
            SetWindowLong(hwnd, GWL_USERDATA, (LONG)conf);

            // PR_PST_PATH
            if( tmpDbFilename
                    && (SetDlgItemTextW(hwnd, IDC_DATAFILE_EDIT, tmpDbFilename) == 0) )
            {
                OTLKCON_LOG_PRINT_LAST_ERROR();
            }

            // PR_OTLKCON_XP_ENABLED
            if( CheckDlgButton(hwnd, IDC_ENABLE_XPP_CHECK,
                                tmpXPEnable?BST_CHECKED:BST_UNCHECKED) == 0 )
            {
                OTLKCON_LOG_PRINT_LAST_ERROR();
            }

            return TRUE;

        case WM_NOTIFY:
            switch (((NMHDR*)lparam)->code)
            {
                case PSN_APPLY:
                    conf = (otlkcon_config *)GetWindowLong(hwnd, GWL_USERDATA);
                    tmpDbFilename = (wchar_t *)calloc(1, (MAX_PATH+1)*sizeof(wchar_t));

                    // PR_PST_PATH
                    if( GetDlgItemTextW(hwnd, IDC_DATAFILE_EDIT, tmpDbFilename, MAX_PATH)
                                                == 0 )
                    {
                        OTLKCON_LOG_PRINT_LAST_ERROR();
                    }
                    conf->dbFilename = tmpDbFilename;

                    // PR_OTLKCON_XP_ENABLED
                    if( IsDlgButtonChecked(hwnd, IDC_ENABLE_XPP_CHECK )
                                                            == BST_CHECKED )
                    {
                        conf->xpEnabled = true;
                    }
                    else
                    {
                        conf->xpEnabled = false;
                    }
                    return FALSE;
            }
            return FALSE;

         case WM_NOTIFY:

             return DefDlgProc(hwnd, uMsg, wparam, lparam ); // <-------------------------!!!

             break;
   }
    return TRUE;
}

That's it.
jkrCommented:
BTW, to elaborate - by ommiting that call to 'DefDlgProc()', you don't give Outlook a chance to process the incoming paint messages, you're just discarding them that way. That's why your GUI isn't being redrawn. Adding the call will ensure that the messages that you don't handle in your DlgProc are processed by the system.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
k3rv1nAuthor Commented:
Thanks a lot!  That was the problem.

Just one small thing.  DefDlgProc() produced a stack overflow.  The MSDN documentation said that it cannot be used in a dialog ( some some types of windows or something ).  I replaced the function with DefWindowProc() and the problem was fixed.

ie.
        default:
            return DefWindowProc (hwnd, uMsg, wparam, lparam);

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.