basjak basjak - 3 months ago 12
C++ Question

File Dialog does not get refreshed unless CFrameWnd is hidden

I am updating some old software that does not work on Win7 or later. so, I am rebuilding some MFC libraries that are using latest win32 updates.

Now I have two issues:


  1. MessageBox appears behind the CFrameWnd so it can't be accessed sending the application to halt.

  2. Open dialog box (whether is based on CFileDialog or IFileDilog) does not get refreshed when changing the file type.



However, both problems are solved if the CFrameWnd is hidden. or, in case of MessageBox, you will not need to hide the window if you write: PostMessage(0x118); which in fact I don't know why.

There must be something I am missing Here.

I also Have another problem when using the OpenFileDialog class that inherits from the IFileDialog. is when closing this dialog without picking up a file, the application Crashes.

//--targetver.h
#pragma once
#include <sdkddkver.h>

//--stdafx.h:
#ifndef CS_EXTRALEAN
#define CS_EXTRALEAN
#endif
#pragma once
#include "targetver.h"
#include<afxwin.h>
#include<afxext.h>
#include<afxcmn.h>

//--stdafx.cpp
#include "stdafx.h"

//--CMainWnd.h
#pragma once

class CMainWnd : public CFrameWnd
{
public:
CMainWnd();
~CMainWnd();

afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT, CPoint);

DECLARE_MESSAGE_MAP()
};

//--CMainWnd.cpp
#include "stdafx.h"
#include"CMainWnd.h"

BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

CMainWnd::CMainWnd()
: CFrameWnd()
{
CString class_name = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
AfxGetApp()->LoadStandardCursor(IDC_ARROW),
(HBRUSH)::GetStockObject(BLACK_BRUSH),
AfxGetApp()->LoadStandardIcon(IDI_ASTERISK));

HRESULT hResult = this->Create(
class_name,
L"This is CMainWnd",
WS_OVERLAPPEDWINDOW,
this->rectDefault,
NULL,
NULL,
0,
NULL);
}

CMainWnd::~CMainWnd() { }

void CMainWnd::OnPaint()
{ }

void CMainWnd::OnLButtonDown(UINT, CPoint)
{
MessageBox(L"HELLO MFC", L"MFC", MB_OK);
}

//--CAppWnd.h
#pragma once

class CAppWnd : public CWinApp
{
public:
CAppWnd();
~CAppWnd();

BOOL InitInstance();

DECLARE_MESSAGE_MAP()
};

//--CAppWnd.cpp
#include "stdafx.h"
#include "CAppWnd.h"
#include "CMainWnd.h"

BEGIN_MESSAGE_MAP(CAppWnd, CWinApp)
END_MESSAGE_MAP()

CAppWnd::CAppWnd()
:CWinApp()
{ }

CAppWnd::~CAppWnd()
{ }

BOOL CAppWnd::InitInstance()
{
this->m_pMainWnd = new CMainWnd;
this->m_pMainWnd->ShowWindow(m_nCmdShow);

return CWinApp::InitInstance();
}

CAppWnd The_App;

Answer

There was a simple problem. You override OnPaint but didn't call the default procedure. OnPaint handles to WM_PAINT message, it doesn't forgive this error.

void CMainWnd::OnPaint()
{ 
    CFrameWnd::OnPaint(); //<= this was missing

    //custom paint...
    //CClientDC dc(this);
    //dc.TextOut(0, 0, L"test");
    //dc is automatically released...
}

Or you can use CPaintDC which is a wrapper for BeginPaint/EndPaint API

void CMainWnd::OnPaint()
{ 
    CPaintDC dc(this);

    //custom paint...
    //dc.TextOut(0, 0, L"test");
    //dc is automatically released...
}

If you don't do any painting in this frame window then remove the whole CMainWnd::OnPaint() function and the correspoonding ON_WM_PAINT message.

Above change should fix your error. I would rewrite the rest of the code so it calls the default override first. Example:

#include "stdafx.h"
#include "resource.h"

class CMainWnd : public CFrameWnd
{
public:
    CMainWnd();
    ~CMainWnd();
    afx_msg void OnPaint();
    afx_msg void OnLButtonDown(UINT, CPoint);
    DECLARE_MESSAGE_MAP()
};

BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
    ON_WM_PAINT()
    ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

CMainWnd::CMainWnd() : CFrameWnd() {}
CMainWnd::~CMainWnd() {}

void CMainWnd::OnPaint()
{ 
    CFrameWnd::OnPaint();
}

void CMainWnd::OnLButtonDown(UINT f, CPoint pt)
{
    CFrameWnd::OnLButtonDown(f, pt);
    CFileDialog dlg(TRUE, 0, 0, 0, 
        L"All files|*.*|" 
        L"Text files|*.txt;*.txt||" , this);
    if (dlg.DoModal() == IDOK)
        MessageBox(dlg.GetPathName(), L"MFC", MB_OK);
}

class CAppWnd : public CWinApp
{
public:
    BOOL InitInstance();
};

BOOL CAppWnd::InitInstance()
{
    CWinApp::InitInstance();
    CMainWnd *frame = new CMainWnd;
    CString class_name = AfxRegisterWndClass(
        CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
        AfxGetApp()->LoadStandardCursor(IDC_ARROW),
        (HBRUSH)::GetStockObject(BLACK_BRUSH),
        AfxGetApp()->LoadStandardIcon(IDI_ASTERISK));

    frame->Create(class_name, L"This is CMainWnd", 
        WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault, NULL, NULL, 0, NULL);
    frame->ShowWindow(m_nCmdShow);
    m_pMainWnd = frame;
    return TRUE;
}

CAppWnd The_App;

Note that you can call up static members directly, for example CFrameWnd::rectDefault, it doesn't cause an error either way but it makes the code more clear.