how to end dialog box(i.e propertysheet) programmatically - c++

I'm trying to close dialog box (which is basically derived from propertysheet class) from code. following is my code:
LRESULT CSettingsSheet::OnCloseSettings(WPARAM wParam, LPARAM lParam)
{
EndDialog(IDCANCEL);
return 0;
}
the issue is endDialog terminates not only dialog box but also main application window. what could be the reason for this problem?
BTW i create this dialog box in main window as follow
if(settingsSheet.DoModal() == IDOK)
{
}
else
{
}
ideally i should set this domodal value with IDCANCEL instead of calling end dialog.
Thanks,
Khurram.

You need to send PSM_PRESSBUTTON message to the property sheet window:
Simulates the selection of a property sheet button. You can send this message explicitly or by using the PropSheet_PressButton macro.
PSBTN_CANCEL - Selects the Cancel button.
PSBTN_OK - Selects the OK button. This value is not valid when using the Aero wizard style (PSH_AEROWIZARD).

The MFC has a function for this CPropertySheet::PressButton.

Related

sendMessage to a hidden window did not work

i want to send a click message on button of a window that it's caption is "Form1" and button's caption is "button1" here is my code:
i checked this handles by SPY++ seems correct..
#include "stdafx.h"
#include <windows.h>
#include <conio.h>
int main()
{
while(1)
{
HWND HWin, btn;
HWin = FindWindowExA(NULL,NULL,NULL,"Form1");
btn = FindWindowExA(HWin,0,NULL,"button1");
SendMessage(btn,BM_CLICK,0,0);
_getch();
}
}
this code worked well and every thing is good... but when "Form1" is set to hidden sendMessage seems not work! Why???
notice that FindWindowExA(...) still return same handle while "Form1" is hidden, and is equal with previous (when is shown)
setting hidden/show of "Form1" is done by this lines:
to shown:
ShowWindow(HWin,SW_SHOW);
to hidden:
ShowWindow(HWin,SW_HIDE);
i'm running on VS 2010
i want to know if sendMessage not work on hidden window is there other way to do that??
thanks All
I'm assuming you are judiciously checking to make sure that your FindWindow calls are not returning NULL when the window is hidden before executing the message passing code.
Assuming you are getting valid HWNDs returned from FindWindow, instead of BM_CLICK message sent to the button itself. Try sending a WM_COMMAND message to the parent window.
if (HWin && btn)
{
LONG ctrlId = GetWindowLong(btn, GWL_ID);
SendMessage(HWin, WM_COMMAND, MAKEWORD((WORD)ctrlId, BN_CLICKED), (LPARAM)btn);
}
If the application itself is in a state where it's not expecting click notifications while hidden, you risk some really weird behavior.
I would think this would work for a win32 app or dialog. Not sure about a .NET forms app.

How can I force a modeless dialogue to close?

I have seen a similar question here:
How to close a modeless MFC dialog in C++
This is how I close my modeless dialogue:
void CChristianLifeMinistryEditorDlg::OnDestroy()
{
if (m_pAssignHistoryDlg != NULL)
{
delete m_pAssignHistoryDlg;
m_pAssignHistoryDlg = NULL;
}
CDialogEx::OnDestroy();
}
This has always been sufficient, until today. What I have found out (quote by chance) is that if the modeless dialogue has a message box up, and the user goes and closes the parent dialogue, the modeless dialogue stays on screen until you close the message box.
The modelless dialogue is clearly still within an event handler since it has just performed some action and displayed the results to the user.
Is it possible to force it to shut? Or should I somehow stop my parent dialogue from being closed whilst the modelless popup is on screen?
What is the right thing to do?
Thank you.
Update:
I tried this:
void CChristianLifeMinistryEditorDlg::OnDestroy()
{
if (m_pAssignHistoryDlg != NULL)
{
CWnd *pPopupMessage = m_pAssignHistoryDlg->GetWindow(GW_ENABLEDPOPUP);
if (pPopupMessage != NULL)
pPopupMessage->PostMessage(WM_CLOSE);
delete m_pAssignHistoryDlg;
m_pAssignHistoryDlg = NULL;
}
CDialogEx::OnDestroy();
}
It didn't work. When I debugged, it refused to process that call etc until I had dismissed the popup message box myself.
Things are further complicated by the fact the the modelless dialogue makes use of two message boxes:
Are you sure you want to delete the name? YES | NO
Name deleted OK
Either the code can be changed to work, or if I go the custom message route I need to know the result of the message box before my code can proceed (for scenario 1).
Update 2:
I am now confused. I added a custom registered message in the parent dialogue:
afx_msg LRESULT CChristianLifeMinistryEditorDlg::OnDisplayMessage(WPARAM wParam, LPARAM lParam)
{
return AfxMessageBox((LPCTSTR)wParam, (UINT)lParam);
}
The modeless dialogue invokes it like this:
iResult = ::SendMessage(GetParent()->GetSafeHwnd(), UWM_DISPLAY_MESSAGE_MSG,
(WPARAM)strEntry.GetBuffer(_MAX_PATH), MB_YESNO | MB_ICONQUESTION);
strEntry.ReleaseBuffer();
I have placed a breakpoint in the message handler so I know it is being fired correctly. And indeed a message box is being displayed.
But for some reason, the message box is still showing central to the modeless dialogue and not the editor. I don't understand why?
Result!
I found this topic: How to force AfxMessageBox to center on mainframe and not whatever child window that currently has focus
I adjusted my code:
afx_msg LRESULT CChristianLifeMinistryEditorDlg::OnDisplayMessage(WPARAM wParam, LPARAM lParam)
{
return MessageBox((LPCTSTR)wParam, NULL, (UINT)lParam);
}
Now it shows center of the parent dialogue.
I do apologize that this question started of in one direction and ended up with an answer in another direction. I am not sure what we do about that? Technically, the comment to me to use GetWindow didn't seem to work for me. So as such, there is no answer. But by changing my design I have been able to prevent the situation.
Premature Result
Whilst the message box showed centered, it affects the subsequent code. Coming up with read allocation errors.
But I have come up with a viable solution now:
GetParent()->EnableWindow(FALSE);
strEntry.Format(IDS_TPL_SURE_DELETE_FROM_ASSIGN_HIST, psHist->strName);
if (AfxMessageBox(strEntry, MB_YESNO | MB_ICONQUESTION) == IDNO)
{
GetParent()->EnableWindow(TRUE);
return;
}
I disable the parent before showing the message box and enable it again once it is dismissed. This prevents the user from closing the main window. They much close the popup message. I will have to go this way for now.
Thanks guys.

MFC Have enter key act as "apply" button

In a certain dialog I would like when the user presses the enter key for it to act as an "apply" button. So far I have at least been able to make the dialog not close upon pressing enter by overriding CWnd::PreTranslateMessage, so currently it just does nothing and I'm not sure how to send apply command from there.
Every dialog should have one and only one button with the BS_DEFPUSHBUTTON style, which indicates to the dialog that this is the button to activate with the Enter key. Usually this is the OK button, but you can make it the Apply button if you want to.
As Mark pointed out above the dialog manager already has all the logic built in to handle the Enter key by invoking the command associated with the default button. You can statically assign the BS_DEFPUSHBUTTON style or handle the DM_GETDEFID message.
The former is trivially easy and the latter is fairly simple to implement. Make sure you set the Default Button property to False for all buttons on your dialog. Now add a message handler for the DM_GETDEFID message. There is no dedicated macro for this message so you have to use the generic handler:
BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
...
ON_MESSAGE(DM_GETDEFID, OnGetDefId)
END_MESSAGE_MAP()
The message handler is equally simple and uses the default message handler signature:
LRESULT CMyDialog::OnGetDefId(WPARAM wParam, LPARAM lParam)
{
return MAKELRESULT(ID_APPLY, DC_HASDEFID);
}
The message handler must return a value whose high-order word contains DC_HASDEFID and the low-order word contains the control ID.
If you navigate over the controls of the dialog you will see that the Apply button has the typical default button visual cue while focus is not on another command button. Pressing Enter while a non-button control has the input focus invokes the default button's command handler. No additional code required.
If your intent is to handle the Enter key without dismissing the dialog, you may be going about it incorrectly. Please take a look at this MSDN article. While using PreTranslateMessage should work, it is not the best way to handle these types of events.
You'll need to handle the OnKeyDown message, and handle the VK_RETURN character inside that function.
void MyCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(nChar == VK_RETURN)
{
// Do Stuff
return;
}
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
Another way to overwrite the message.
BOOL CMyDialog::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_RETURN:
{
UINT nID = ::GetDlgCtrlID(pMsg->hwnd);
if (nID == ID_APPLY)
{
//DO YOUR STUFF HERE
}
}
break;
default:
break;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
Also, you don't need to use PreTranslateMessage if you are using ::OnKeyDown

How do I use Dialog resources in Win32?

Without resources I can create my UI with a complex array of CreateWindow() and CreateWindowEx(), and WndProc() to process my events.
I noticed if I right-click in the resource view and click "add resource", I can draw a dialog box with all the controls. This would save me a huge amount of time if I could draw the interface like I normally do with C#.
After I've drawn the interface with the resource editor, how do I then create the window from code? Can someone provide a very simple example with a button, and show how to handle a WM_COMMAND event on that button please?
Also, is this generally how people create the GUI? Is there any loss in flexible to do this way? Even in C# I often have to supplement designer-generated UI with my own code-generated UI, but the majority of the time I'm quite happy to use designer.
After creating the dialog in the resource editor, call CreateDialog(modeless dialog;you need to dispatch the messages manually just like when you use CreateWindow) or DialogBox(modal dialog; the function does not return until you close the dialog. it does the dispatching for you) to make the dialog show up. Just like you pass in the window proc to RegisterClass, you pass the dialog proc to those functions for the dialog call back. An example of DialogProc looks likes this:
BOOL DialogProc( HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam ){
switch( iMessage ){
case WM_COMMAND:
switch( LOWORD( wParam ) ){
case BTOK:
MessageBox( hDlg, "Hello, World!", NULL, NULL );
return TRUE;
break;
}
break;
}
return FALSE;
}
This is a basic way of creating a dialog. More sophisticated method would normally involve OOP, usually wrapping each resource( button, window, etc) as a C++ object or using MFC.
If you have placed your button or any control on some dialog, that control is already in created state. For handling the messages of these child controls on this dialog , you have to override OnCommand Method in the class which is implementing your dialog.
For Example:
//CDialog_ControlDlg is my Dialog class derived from CDialog
//IDC_BUTTON_SAMPLE is the ID of the button which was palced on the dialog in the resource Editor..
BOOL CDialog_ControlDlg::OnCommand(WPARAM wParam,LPARAM lparam){
int iNotiFicationMsg=HIWORD(wParam);//This is thenotification Msg from the child control
int iCommandId=LOWORD(wParam);//And Control ID of the Child control which caused that Msg
BOOL result=FALSE;
switch(iCommandId){
case IDC_BUTTON_SAMPLE:
if(iNotiFicationMsg==BN_CLICKED)
{
//Your Code for handling this type of Msg for this control..
}
break;
default:
{
//Specific Code;
}
return result;
}
}

Why doesn't OnKeyDown catch key events in a dialog-based MFC project?

I just create a dialog-based project in MFC (VS2008) and add OnKeyDown event to the dialog.
When I run the project and press the keys on the keyboard, nothing happens. But, if I remove all the controls from the dialog and rerun the project it works.
What should I do to get key events even when I have controls on the dialog?
Here's a piece of code:
void CgDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
AfxMessageBox(L"Key down!");
CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}
When a dialog has controls on it, the dialog itself never gets the focus. It's stolen by the child controls. When you press a button, a WM_KEYDOWN message is sent to the control with focus so your CgDlg::OnKeyDown is never called. Override the dialog's PreTranslateMessage function if you want dialog to handle the WM_KEYDOWN message:
BOOL CgDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN )
{
if(pMsg->wParam == VK_DOWN)
{
...
}
else if(pMsg->wParam == ...)
{
...
}
...
else
{
...
}
}
return CDialog::PreTranslateMessage(pMsg);
}
Also see this article on CodeProject: http://www.codeproject.com/KB/dialog/pretransdialog01.aspx
Many of my CDialog apps use OnKeyDown(). As long you only want to receive key presses and draw on the screen (as in make a game), delete the default buttons and static text (the CDialog must be empty) and OnKeyDown() will start working. Once controls are placed on the CDialog, OnKeyDown() will no longer be called.