Solved

Centering derived CFileDialog with Hook function enabled.

Posted on 2004-10-02
10
1,113 Views
Last Modified: 2013-11-20
My problem is that if you define a hook function for a CFileDialog object, I can not figure out how to convert the HWND parameter to a CWnd parameter and call the CenterWindow function.

Here is how I create my File Dialog object…

CFileDialog cDlg(TRUE, "txt", NULL,
OFN_SHOWHELP|OFN_FILEMUSTEXIST|OFN_EXPLORER|
OFN_ENABLEHOOK,
strFilter, pFrameWnd );      // pFrameWnd is set to my MDI Frame

cDlg.m_ofn.lStructSize          = sizeof(OPENFILENAME);
cDlg.m_ofn.hInstance        = AfxGetInstanceHandle();
cDlg.m_ofn.lpstrCustomFilter= NULL;
cDlg.m_ofn.nMaxCustFilter   = 0;
cDlg.m_ofn.nFilterIndex     = 0;
cDlg.m_ofn.lpstrFile        = (LPSTR)fileName;
cDlg.m_ofn.nMaxFile         = sizeof(fileName);
cDlg.m_ofn.lpstrFileTitle   = NULL;
cDlg.m_ofn.nMaxFileTitle    = 0;
cDlg.m_ofn.lpstrInitialDir  = NULL;
cDlg.m_ofn.lpstrTitle       = NULL;
cDlg.m_ofn.nFileOffset      = 0;
cDlg.m_ofn.nFileExtension   = 0;
cDlg.m_ofn.lCustData        = 0;
cDlg.m_ofn.lpTemplateName   = NULL;
cDlg.m_ofn.lpfnHook   = FileOpenHookFunction;

cDlg.DoModal();            // I am not testing the return value yet (testing now).

Here is my hook function…

UINT CALLBACK FileOpenHookFunction( HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam )
{
      CModelXApp* pApp = (CModelXApp *) AfxGetApp();
      CWnd* pWnd = CWnd::FromHandlePermanent( hdlg );
      LPOFNOTIFY lpon;

      switch ( uiMsg )
      {
      case CDN_INITDONE:

            lpon = (LPOFNOTIFY)lParam;
            if ((pWnd != NULL) && (lpon->hdr.code == CDN_INITDONE))
            {
                  pWnd->CenterWindow();
            }
            break;

      case WM_PAINT:
      case WM_SHOWWINDOW:

            // Redraw views so that when moving the file open dialog box, there is not gray area.
            if ((pApp != NULL) && (pApp->m_pMainFrameWindow != NULL))
                  pApp->m_pMainFrameWindow->OnRender();
            break;

      default:
            break;
      }
      return false;
}

I have tested in debug mode and the function is not receiving the CDN_INITDONE message.  What do I have to do in order to receive this message.  According to the MFC documentation, all you have to specify is the OFN_EXPLORER style which I do, but I still am not receiving the CDN_INITDONE message.

Also, if you define a derived class for the CFileDialog class, you can not use a hook function because all messages will be sent to the hook function and not the message  functions you have overridden.  I kind of need to use a hook function because I want to be able to redraw the views underneath the file dialog before it is displayed (WM_PAINT and WM_SHOWWINDOW) – if I do not, they will all be dark gray.  I have tried to override the OnPaint and OnShowWindow functions with a class derived from CFileDialog and not use a hook function and redraw my views with my OnRender() function, but the views keep getting erased (dark-gray).

As it is now, the messages WM_PAINT and WM_SHOWWINDOW work fine inside the hook function (my views are updated before the file dialog window is shown).  But I can not get the file dialog window to be centered.

If you know how to fix this, I would appreciate it – I would also like to know if I am setting pWnd correctly in the hook function …CWnd* pWnd = CWnd::FromHandlePermanent( hdlg ).
0
Comment
Question by:danielvallas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 2
10 Comments
 

Author Comment

by:danielvallas
ID: 12206940
I figured out how to receive the message...
case CDN_INITDONE, should be case WM_NOTIFY.
The CDN_INITDONE message comes in as a WM_NOTIFY message.

However, when CenterWindow is called it gives me an ASSERT error because m_hWnd is NULL.
I tried using a pointer to my CFileDialog object ( CFileDialog* pOpenFile = &cDlg; ) before calling cDlg.DoModal(), and then use that pointer to call CenterWindow() (pOpenFile->CenterWindow()) in the hook function under the WM_NOTIFY message, but I keep getting an ASSERT error because pOpenFile->m_hWnd == NULL.

Any Help?
0
 

Author Comment

by:danielvallas
ID: 12206953
I have noticied that the HWND hdlg parameter passed into the hook function is not NULL when the WM_NOTIFY message is passed.  How do you convert HWND hdlg that is passed into the hook function to a valid CWnd pointer, in order to call CWnd::CenterWindow() ????
0
 
LVL 15

Expert Comment

by:lakshman_ce
ID: 12207080
Try using FromHandle method

CWnd::FromHandlePermanent  
Returns a pointer to a CWnd object when given a handle to a window. If a CWnd object is not attached to the handle, NULL is returned.This function, unlike FromHandle, does not create temporary objects.
CWnd::FromHandle  
Returns a pointer to a CWnd object when given a handle to a window. If a CWnd object is not attached to the handle, a temporary CWnd object is created and attached.The pointer may be temporary and should not be stored for later use.

Also you can have a look at
http://www.codeguru.com/Cpp/controls/toolbar/miscellaneous/article.php/c5497/
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:danielvallas
ID: 12207340
What I just tried is writing my own CenterWindow function, here it is:

void CenterHWnd( HWND *pWnd, HWND *pParent )
{
     RECT m_rParentRect, m_rChildRect;
     int x, y, dx, dy;

     ::GetWindowRect( *pParent, &m_rParentRect );
     ::GetWindowRect( *pWnd,    &m_rChildRect );

     x  = (m_rParentRect.right -
          (m_rChildRect.right - m_rChildRect.left)) / 2;
     y  = (m_rParentRect.bottom -
          (m_rChildRect.bottom - m_rChildRect.top)) / 2;
     dx = (m_rChildRect.right  - m_rChildRect.left);
     dy = (m_rChildRect.bottom - m_rChildRect.top);

     ::SetWindowPos( *pWnd, NULL, x, y, dx, dy, SWP_NOSIZE|SWP_NOZORDER );
}

I then call it under the WM_NOTiFY message in my hook function...

case WM_NOTIFY:
   lpon = (LPOFNOTIFY)lParam;
   if (lpon->hdr.code == CDN_INITDONE)
      CenterHWnd( GetParent(hdlg), pFrameWnd->m_hWnd );
   break;

This does center the window, but I have the same problem (as I did without using a hook function) of my splitter pane render views underneith being erased when the open file dialog box is centered.  Even if I render my views before or after centering the window with my CenterHWnd function, the render views are still erased.  If I take out this function, the views are NOT erased, but of course, the window is not centered.

(The splitter pane views underneith the open file dialog window are actually Direct3D device views).

Is there a message for redrawing the window that I am missing, other than WM_PAINT and WM_SHOWWINDOW ???
0
 

Author Comment

by:danielvallas
ID: 12207360
Also,

FromHandle(), FromHandlePermanent(), and Attach() I have tried.  It was esier to write my own centerwindow function using HWND handles, instead of trying to figure out which function to use to build a CWnd from an HWND handle.
0
 

Author Comment

by:danielvallas
ID: 12207730
lakshman_ce,

Your link was no help - the example on that site does not use a hook function.
0
 
LVL 15

Expert Comment

by:lakshman_ce
ID: 12208238
Yes it doesn't use hooks, but it is to give an idea with the code fragments

void CFileDialogEx::OnInitDone()
{
   CWnd* wndParent = GetParent();
   ASSERT(wndParent != NULL);

   // Display File dialog in center
   wndParent->CenterWindow();

...

}

static CFileDialogEx* GetFileDlg (HWND hwdParent)
{
   CFileDialog* pDlg =
         (CFileDialog*)CWnd::FromHandle (hwdParent);
   ASSERT (pDlg != NULL);

   CFileDialogEx* pFD = (CFileDialogEx*) pDlg->GetDlgItem(0);
   ASSERT (pFD != NULL);

   return pFD;
}

0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 12867792
PAQed with points refunded (500)

modulo
Community Support Moderator
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
ffmpeg - "rtsp://...... Operation not permitted" 4 92
canBalance challenge 34 114
sumHeights  challenge 17 83
Fibonacci challenge 11 141
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question