Showing MFC tooltips for controls nested inside another control - mfc

For some reasons I have a parent window. This window contains normal controls. But it also takes child controls that again have controls in it. The real application is more complex. In the real version I also use WS_EX_CONTROLPARENT to allow navigation in the dialog between the nested controls.
For simplicity I created a dialog base application. In there is a normal edit control and a static control with an edit control in it. I just created the edit control inside my code.
I enabled the tool tips. In the normal way. Tooltips are shown for the buttons and the normal edit control. But the control inside the static doesn't show a tooltip.
How to get the tools tips for the nested controls too inside my handler?
Here the code for the CPP.
// ToolTipTestDlg.cpp : implementation file
#include "pch.h"
#include "framework.h"
#include "ToolTipTest.h"
#include "ToolTipTestDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CToolTipTestDlg dialog
CToolTipTestDlg::CToolTipTestDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_TOOLTIPTEST_DIALOG, pParent)
{
EnableToolTips();
}
void CToolTipTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CONTAINER, m_container);
}
BEGIN_MESSAGE_MAP(CToolTipTestDlg, CDialogEx)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
// CToolTipTestDlg message handlers
BOOL CToolTipTestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
m_edit1.Create(WS_CHILD | WS_BORDER | WS_VISIBLE, CRect(10, 10, 110, 30), this, 1);
m_edit2.Create(WS_CHILD | WS_BORDER | WS_VISIBLE, CRect(10, 10, 110, 30), &m_container, 1);
return TRUE; // return TRUE unless you set the focus to a control
}
BOOL CToolTipTestDlg::OnToolTipText(UINT nId, NMHDR* pNMHDR, LRESULT* pResult)
{
// For all keyboard messages we need to know the target of the message
ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
TOOLTIPTEXTW* pTTTW = reinterpret_cast<NMTTDISPINFO*>(pNMHDR);
CString strTipText = _T("Test");
wcsncpy_s(pTTTW->szText, _countof(pTTTW->szText), CT2W(strTipText), _countof(pTTTW->szText));
*pResult = 0;
return TRUE; // message was handled
}
The header file:
// ToolTipTestDlg.h : header file
#pragma once
// CToolTipTestDlg dialog
class CToolTipTestDlg : public CDialogEx
{
// Construction
public:
CToolTipTestDlg(CWnd* pParent = nullptr); // standard constructor
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TOOLTIPTEST_DIALOG };
#endif
CEdit m_edit1, m_edit2;
CStatic m_container;
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
// Generated message map functions
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
afx_msg BOOL OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult);
};
And the RC file with the container:
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_TOOLTIPTEST_DIALOG DIALOGEX 0, 0, 321, 96
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,79,75,50,14
PUSHBUTTON "Cancel",IDCANCEL,134,75,50,14
LTEXT " ",IDC_CONTAINER,7,39,168,25,SS_NOTIFY
END

My investigation showed that this MFC tooltip implementation is only designed for controls that are direct children for the control that called EnabledToolTips.
I found an solution that works. It may not be the best but it is easy to implement.
I use an own container class (in my real world code this class already exists)
class CStaticContainer : public CStatic
{
public:
DECLARE_MESSAGE_MAP()
afx_msg BOOL OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult);
};
I made sure that this container class is used and subclassed the existing CStatic (here the code for the sample in the dialog class):
// In the dialog class
CStaticContainer m_container;
...
void CToolTipTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CONTAINER, m_container);
}
I enabled tooltips for the container too in OnInitDialog.
m_container.EnableToolTips();
For the container class I added a TTN_NEEDTEXT handler. It just forwards the message to the outer parent.
BEGIN_MESSAGE_MAP(CStaticContainer, CStatic)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
BOOL CStaticContainer::OnToolTipText(UINT nId, NMHDR* pNMHDR, LRESULT* pResult)
{
GetParent()->SendMessage(WM_NOTIFY, nId, reinterpret_cast<LPARAM>(pNMHDR));
return TRUE; // message was handled
}
Now the tool tips show up for all controls.

Related

How to make one frame can switch page? like a web browser

I still learn mfc, i want to create application like webbrowser. it have seperate page that can call anytime. I try to implement that. But i can't implement the 2nd page and so on. in the code only have 2 pages. login and logout page. i put login in render method. but i dont know how to implement 2nd page (logout). for now i just directly put it inside login method. can u show me in mfc ways to achieve this?
#include <afxwin.h>
#define LOGIN_BTN 5
#define LOGOUT_BTN 6
class CMainFrame: public CFrameWnd
{
CPoint mCoordinate;
CSize mDimension;
public:
CMainFrame()
{
// Get primary screen resolution
int widthScreen = GetSystemMetrics(SM_CXSCREEN);
int heightScreen = GetSystemMetrics(SM_CYSCREEN);
// Set size and position to middle screen
mDimension.cx = 280;
mDimension.cy = 133;
mCoordinate.x = (widthScreen / 2) - (mDimension.cx / 2);
mCoordinate.y = (heightScreen / 2) - (mDimension.cy / 2);
Create(
NULL,
"Pandora",
WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU,
CRect(mCoordinate, mDimension));
};
void render()
{
CButton* loginBtn = new CButton();
loginBtn->Create(
"Login",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
CRect(CPoint(100, 60), CSize(150, 25)),
this, LOGIN_BTN);
};
void removeAllChild()
{
CWnd* pChild = nullptr;
while(true)
{
pChild = GetWindow(GW_CHILD);
if(pChild == NULL) { break; }
delete pChild;
};
};
protected:
afx_msg int OnCreate(LPCREATESTRUCT);
afx_msg void login();
afx_msg void logout();
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
ON_COMMAND(LOGIN_BTN, &CMainFrame::login)
ON_COMMAND(LOGOUT_BTN, &CMainFrame::logout)
END_MESSAGE_MAP()
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
render();
return 0;
};
void CMainFrame::login()
{
// delete all child
removeAllChild();
// How to make this logout button such it in 2nd page?
CButton* logoutBtn = new CButton;
logoutBtn->Create(
"Logout",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
CRect(CPoint(40, 32), CSize(200, 70)),
this, LOGOUT_BTN);
};
void CMainFrame::logout()
{
removeAllChild();
render();
};
class CApplication : public CWinApp {
BOOL InitInstance() {
CMainFrame* mainWnd = new CMainFrame();
m_pMainWnd = mainWnd;
mainWnd->ShowWindow(SW_NORMAL);
mainWnd->UpdateWindow();
return TRUE;
}
};
CApplication app;
You could refer to the document : Adding Multiple Views to a Single Document. Also here is a similar thread may help: How to change MFC View by clicking a Button inside the MainFrame.
You could use the code below to switch the view:
pActiveView->ShowWindow(SW_HIDE);
pNewView->ShowWindow(SW_SHOW);
((CFrameWnd *)m_pMainWnd)->SetActiveView(pNewView);
((CFrameWnd *)m_pMainWnd)->RecalcLayout();
pNewView->Invalidate();

Reduced label is displayed in c++ mfc application

I develop some C++ MFC application. In my dialog box there is a progress bar and one label with constant text (cyrillic symbols).
On Windows 7,XP this text is displayed good but on Windows 8,10 it is displayed in reduced form.
Why?
This is on Windows 7:
And this is on Windows 8:
This is a source code of the class related to this Dialog Form.
*.cpp file:
// Progress.cpp : implementation file
//
#include "stdafx.h"
#include "LybidLoader.h"
#include "Progress.h"
#include "afxdialogex.h"
// Progress dialog
IMPLEMENT_DYNAMIC(Progress, CDialogEx)
Progress::Progress(CWnd* pParent /*=NULL*/)
: CDialogEx(Progress::IDD, pParent)
{
}
Progress::~Progress()
{
}
void Progress::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_PROGRESS1, m_ProgressBar);
}
BEGIN_MESSAGE_MAP(Progress, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON1, &Progress::OnBnClickedForceExit)
END_MESSAGE_MAP()
// Progress message handlers
BOOL Progress::OnInitDialog()
{
CDialogEx::OnInitDialog();
ModifyStyle( WS_SYSMENU, 0);
m_ProgressBar.SetMarquee(TRUE, 10);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void Progress::OnBnClickedForceExit()
{
if (::MessageBoxW(this->m_hWnd, (LPCWSTR)_T("Ви впевнені? Буде здійснено аварійний вихід"), (LPCWSTR)_T("Підтвердіть дію"), MB_ICONEXCLAMATION | MB_YESNO) == IDYES)
{
PostQuitMessage(0);
}
}
BOOL Progress::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if( pMsg->message == WM_KEYDOWN )
{
if(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
{
return TRUE; // Do not process further
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
And *.h file:
#pragma once
#include "afxcmn.h"
// Progress dialog
class Progress : public CDialogEx
{
DECLARE_DYNAMIC(Progress)
public:
Progress(CWnd* pParent = NULL); // standard constructor
virtual ~Progress();
// Dialog Data
enum { IDD = IDD_PROGRESSBAR };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
CProgressCtrl m_ProgressBar;
afx_msg void OnBnClickedForceExit();
virtual BOOL PreTranslateMessage(MSG* pMsg);
};
And this is a portion of resources file:
IDD_PROGRESSBAR DIALOGEX 0, 0, 369, 105
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Будь-ласка, зачекайте!"
FONT 8, "Microsoft Sans Serif", 400, 0, 0x1
BEGIN
CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_MARQUEE | WS_BORDER,7,47,355,14
LTEXT "Триває обмін даними з опціональною платою! НЕ ВИМИКАЙТЕ РАДІОСТАНЦІЮ",IDC_STATIC,25,19,267,8
PUSHBUTTON "Примусово завершити роботу",IDC_BUTTON1,101,84,118,14
END
Disregard the garbage characters in the following images, it's just a codepage issue.
The space you provide for the static text controls too small:
The first dialog is yours, modify it so that it looks like the second one.
It could be font DPI, or it could be fonts themselves. It could be "Microsoft Sans Serif" maps to a different font. I have worked enough localization to know that some fonts are not available on all systems. I would think that "Microsoft Sans Serif" would probably be, but I have seen systems in the Far East where "Arial" was not on the system.
If I were you, I would change "Microsoft Sans Serif" to "MS Shell Dlg" in your dialog resource. "MS Shell Dlg" is sort of a virtual font that maps roughly to the default GUI font.

VC++ Trasforming a sample application into a DLL

I have a project where I received an sample code that is an exe, that basically loads to a dialog two activeX controls.
I need to make an DLL to use the functions of that controls.
What's the best strategy to do this?
I think my DLL need's to make an instance of the window.
and when the window is build get pointers to the activeX controls to make stuff happen.
What is the best strategy to do this? or if it is even possible?
The App Code:
StartUp.h
#pragma once
#ifndef __AFXWIN_H__
#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h" // main symbols
// CStartUpApp:
// See StartUp.cpp for the implementation of this class
//
class CStartUpApp : public CWinApp
{
public:
CStartUpApp();
// Overrides
public:
virtual BOOL InitInstance();
// Implementation
DECLARE_MESSAGE_MAP()
};
extern CStartUpApp theApp;
StartUpDlg.h
#pragma once
#include "xnssdkdevicectrl.h"
#include "xnssdkwindowctrl.h"
// CStartUpDlg dialog
class CStartUpDlg : public CDialog
{
// Construction
public:
CStartUpDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_STARTUP_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
private:
// [ XNS ACTIVEX HELP ]
// -----------------------------------------------------------------------
// XNS Device control and Window control variables
// -----------------------------------------------------------------------
CXnssdkwindowctrl m_ctrlXnsWindow; // XnsWindow control
CXnssdkdevicectrl m_ctrlXnsDevice; // XnsDevice control
public:
afx_msg void OnBnClickedOk();
};
StartUp.cpp
#include "stdafx.h"
#include "StartUp.h"
#include "StartUpDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CStartUpApp
BEGIN_MESSAGE_MAP(CStartUpApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CStartUpApp construction
CStartUpApp::CStartUpApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
// The one and only CStartUpApp object
CStartUpApp theApp;
// CStartUpApp initialization
BOOL CStartUpApp::InitInstance()
{
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
CStartUpDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
StartUpDlg.cpp
#include "stdafx.h"
#include "StartUp.h"
#include "StartUpDlg.h"
// [ XNS ACTIVEX HELP ]
// -----------------------------------------------------------------------
// This files are installed in {$SDK path}\sample_code\include
// You should include this files
// -----------------------------------------------------------------------
#include "XnsCommon.h"
#include "XnsDeviceInterface.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// Macro for OutputDebugString()
#define DBG_LOG(...) do{\
CString strMessage = _T("");\
strMessage.AppendFormat(_T("(%S:%d)"), __FUNCTION__, __LINE__); \
strMessage.AppendFormat(__VA_ARGS__);\
OutputDebugString(strMessage);\
}while(0);
// Macro for AfxMessageBox()
#define ERROR_BOX(...) do{\
CString strMessage = _T("");\
strMessage.Format(__VA_ARGS__);\
AfxMessageBox(strMessage);\
}while(0);
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CStartUpDlg dialog
CStartUpDlg::CStartUpDlg(CWnd* pParent /*=NULL*/)
: CDialog(CStartUpDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CStartUpDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_XNSSDKDEVICECTRL, m_ctrlXnsDevice);
DDX_Control(pDX, IDC_XNSSDKWINDOWCTRL, m_ctrlXnsWindow);
}
BEGIN_MESSAGE_MAP(CStartUpDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDOK, &CStartUpDlg::OnBnClickedOk)
END_MESSAGE_MAP()
// CStartUpDlg message handlers
BOOL CStartUpDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
// [ XNS ACTIVEX HELP ]
// -----------------------------------------------------------------------
// Initializes the DLL files.
// For this, XnsActiveX library requires config.xml, device.xml,
// and xns.xml files and the DLL file list should be mentioned
// in Xns.xml file. The path of the DLL file can not exceed 512 bytes
// in length. The XnsActiveX library searches for xns.xml using
// XnsSDKDevice.ocx installed in "{$SDK path}\Config" folder.
// -----------------------------------------------------------------------
long nRet = m_ctrlXnsDevice.Initialize();
if (nRet != ERR_SUCCESS)
{
DBG_LOG(_T("XnsSdkDevice:: Initialize() fail: errno=[%d]\n"), nRet);
}
// [ XNS ACTIVEX HELP ]
// -----------------------------------------------------------------------
// Initializes the XnsSdkWindow control.
// Namely, this will specify the window handle in order to display
// images on the screen.
// -----------------------------------------------------------------------
nRet = m_ctrlXnsWindow.Initialize(NULL, NULL);
DBG_LOG(_T("XnsSdkWindow:: Initialize() return=[%d](%s)\n"),
nRet, m_ctrlXnsDevice.GetErrorString(nRet));
return TRUE; // return TRUE unless you set the focus to a control
}
void CStartUpDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CStartUpDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CStartUpDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CStartUpDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
OnOK();
}
my dll header
__declspec(dllexport) long init();//initilize app with activeX controls in window
__declspec(dllexport) long getDlgInstance();//get dlg handle to be able to call activeX
__declspec(dllexport) long connect(long handle);//do stuff
Shouldn't be that hard...
Without having seen your code (how could I?), I assume you defined functions to return the pointers of the activeX controls to the caller.
Judging by the questions you asked earlier you know how to make a DLL. Get all the code you need in a new DLL project, export only the functions you want to access from the host application and you're done
Your DLL code would look something like
__declspec (dllexport) CStartUpDlg *ShowStartUpDlg()
{ AFX_MANAGE_STATE(AfxGetStaticModuleState()); // in case the dialog is in the DLL's .rc file
// alternate to the above line: AfxSetResourceHandle(hInstance); // hInstance is what you get in the DLL's InitInstance()
CStartUpDlg *pDlg = new CStartUpDlg();
if (pDlg == NULL)
return NULL;
if (!pDlg->Create(IDD_STARTUP_DLG))
return NULL;
pDlg->ShowWindow(SW_SHOW);
return pDlg; // make sure you close the dialog and delete pDlg at the end of your program
}

MFC- receiving Button-Click-Message failed

I've created a new dialog in my MFC dialog based application. the new dialog contains 5 control buttons.
the following happens and I don't understand why?
click on buttonX. (result ok, OnBnClicked message is sent)
click on on any place of the application, but not on the dialog.(removing focus from dialog)
click again on buttonX (FAILED, OnBnClicked message is NOT sent). but if instead I click on any other button in the dialog (result ok, OnBnClicked message is sent).
and when I do:
...
...
click on the dialog area just to set focus on the dialog again
click again on buttonX. (result ok, OnBnClicked message is sent)
**I need to do step 3 only if I want to click again on the buttonX! why??
I think it related to SetFocus() but I m not sure how.
the buttons IDC are:
IDC_BACK_MEDIA_PRESS_BUTTON 1180
IDC_TOOLS_LEFT_RIGHT 1024
IDC_MEDIA_FOREWARD_BUTTON 1103
IDC_MEDIA_BACKWARD_BUTTON 1104
IDC_TOOLS_HOOD_BUTTON 2346
the dialog properties is:
IDD_TOOLS_DIALOG DIALOGEX 0, 0, 51, 218
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Tools"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Media &Foreward",IDC_MEDIA_FOREWARD_BUTTON,7,79,37,36,BS_MULTILINE
PUSHBUTTON "&Media &BackWard",IDC_MEDIA_BACKWARD_BUTTON,7,43,37,36,BS_MULTILINE
PUSHBUTTON "Back Media Press",IDC_BACK_MEDIA_PRESS_BUTTON,7,127,37,36,BS_MULTILINE | NOT WS_VISIBLE
PUSHBUTTON "Hood",IDC_TOOLS_HOOD_BUTTON,7,7,37,36
PUSHBUTTON "Left Right",IDC_TOOLS_LEFT_RIGHT,7,175,37,36
END
I've tried different style like, tool windows, overlapped, popup. it happens in all the cases.
Thanks for the help.
.h
class CToolsDlg : public CBDialog
{
DECLARE_DYNAMIC(CToolsDlg)
public:
CToolsDlg(CWnd* pParent = NULL); // standard constructor
virtual ~CToolsDlg();
CToolTipCtrl m_ToolsTips;
// Dialog Data
enum { IDD = IDD_TOOLS_DIALOG };
protected:
virtual void OnCancel();
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
CMFCButton m_HoodButton;
CMFCButton m_MediaForewardButton;
CMFCButton m_MediaBackwardButton;
CMFCButton m_LeftRightButton;
virtual BOOL OnInitDialog();
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnBnClickedCancel();
afx_msg void OnBnClickedToolsHoodButton();
afx_msg void OnBnClickedMediaForewardButton();
afx_msg void OnBnClickedMediaBackwardButton();
afx_msg void OnBnClickedLeftRightButton();
afx_msg void OnBnClickedBackMediaPressButton();
};
.cpp
IMPLEMENT_DYNAMIC(CToolsDlg, CBDialog)
CToolsDlg::CToolsDlg(CWnd* pParent /*=NULL*/)
: CBDialog(CToolsDlg::IDD, pParent)
{
}
CToolsDlg::~CToolsDlg()
{
}
void CToolsDlg::DoDataExchange(CDataExchange* pDX)
{
CBDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TOOLS_HOOD_BUTTON, m_HoodButton);
DDX_Control(pDX, IDC_MEDIA_FOREWARD_BUTTON, m_MediaForewardButton);
DDX_Control(pDX, IDC_MEDIA_BACKWARD_BUTTON, m_MediaBackwardButton);
DDX_Control(pDX, IDC_TOOLS_LEFT_RIGHT, m_LeftRightButton);
}
BEGIN_MESSAGE_MAP(CToolsDlg, CBDialog)
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_WM_TIMER()
ON_BN_CLICKED(IDC_TOOLS_HOOD_BUTTON, &CToolsDlg::OnBnClickedToolsHoodButton)
ON_BN_CLICKED(IDC_MEDIA_FOREWARD_BUTTON, &CToolsDlg::OnBnClickedMediaForewardButton)
ON_BN_CLICKED(IDC_MEDIA_BACKWARD_BUTTON, &CToolsDlg::OnBnClickedMediaBackwardButton)
ON_BN_CLICKED(IDC_TOOLS_LEFT_RIGHT, &CToolsDlg::OnBnClickedLeftRightButton)
ON_BN_CLICKED(IDC_BACK_MEDIA_PRESS_BUTTON, &CToolsDlg::OnBnClickedBackMediaPressButton)
END_MESSAGE_MAP()
// CToolsDlg message handlers
BOOL CToolsDlg::OnInitDialog()
{
CBDialog::OnInitDialog();
// Window position
//////////////////////////////////////////////////////////////////////////
CMainFrame* mf = (CMainFrame*)AfxGetMainWnd();
RECT MFwinRect;
RECT ThiswinRect;
CWnd* fv = mf->m_wndSplitter.GetView( mf->m_wndSplitter.GetCurrentViewIndex(0,0) );
fv->GetWindowRect(&MFwinRect);
GetWindowRect(&ThiswinRect);
MoveWindow(
MFwinRect.right - (ThiswinRect.right - ThiswinRect.left) - 14, // X
MFwinRect.top + 14, // Y
(ThiswinRect.right - ThiswinRect.left), // nWidth
(ThiswinRect.bottom - ThiswinRect.top) ); // nHeight
// Set controls state
//////////////////////////////////////////////////////////////////////////
m_ToolsTips.Create(this);
m_ToolsTips.AddTool(&m_HoodButton, TOOLTIP_HOOD_BUTTON);
m_ToolsTips.AddTool(&m_MediaForewardButton, TOOLTIP_MEDIA_FOREWARD_BUTTON);
m_ToolsTips.AddTool(&m_MediaBackwardButton, TOOLTIP_MEDIA_BACKWARD_BUTTON);
m_ToolsTips.AddTool(&m_LeftRightButton, TOOLTIP_LEFT_RIGHT_BUTTON);
m_ToolsTips.SetDelayTime(1000);
m_ToolsTips.Activate(BARAK_PREFS->m_Params.m_bShowToolTips);
// Main timer loop (no need for now)
// SetTimer( 1, 1000, NULL );
return TRUE;
}
BOOL CToolsDlg::PreTranslateMessage(MSG* pMsg)
{
m_ToolsTips.RelayEvent(pMsg);
return CBDialog::PreTranslateMessage(pMsg);
}
void CToolsDlg::OnCancel()
{
// When closing the window, destroy it and not only hide (its a floating window).
DestroyWindow();
}
void CToolsDlg::OnTimer(UINT_PTR nIDEvent)
{
CBDialog::OnTimer(nIDEvent);
}
void CToolsDlg::OnBnClickedToolsHoodButton()
{
...
}
void CToolsDlg::OnBnClickedMediaForewardButton()
{
...
}
void CToolsDlg::OnBnClickedMediaBackwardButton()
{
...
}
void CToolsDlg::OnBnClickedLeftRightButton()
{
...
}
void CToolsDlg::OnBnClickedBackMediaPressButton()
{
...
}
I see that you are filling view with dialog content. Have you put focusing to your dialog? I think this mystic behavior happening only on first mouse click in your dialog (then dialog gets the focus). I'm just guessing :)

change the background color of a dialog box mfc

I'm trying to change the background color of a dialog box (win 7, vs2010,c++).
I tried to catch WM_CTLCOLOR ,WM_ERASEBKGND and change the color.
I manged to change in this way the backgroung color, but when the window is finish to upload itself, the color is back to default but I noticed that the frame is in the right color.
I think that I'm changing the window and not the dialog box or something like that.
I'm doing this with WTL (not AFX).
What should I do?
Try this:
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CAboutDlg::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
CBrush myBrush(RGB(255, 255, 255)); // dialog background color
CBrush *pOld = pDC->SelectObject(&myBrush);
BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOld); // restore old brush
return bRes; // CDialog::OnEraseBkgnd(pDC);
}
And have a look here
The better way will be to override WM_CTLCOLOR, background of controls such as STATIC will be fill with your color too.
BEGIN_MESSAGE_MAP(YourDlg, CDialogEx)
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
...
HBRUSH YourDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
return (HBRUSH)GetStockObject(WHITE_BRUSH);
}
The above answer will work only if you don't have a tab inside dialog box it will color background of dialog box other the tab portion. For the tab portion you have to create a new derived class with base class CTabCtrl.