sendMessage to a hidden window did not work - c++

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.

Related

How do I programmatically maximize a top-level window in a Win32 C++ program?

I'm trying to programmatically maximize my top-level window in my Win32 C++ program. I'm using code similar to the following in the code that handles the WM_CREATE message:
WINDOWPLACEMENT windowPlacement = {};
windowPlacement.length = sizeof(WINDOWPLACEMENT);
windowPlacement.rcNormalPosition = newWindowRect;
windowPlacement.showCmd = SW_NORMAL;
if (maximized == TRUE)
{
windowPlacement.showCmd = SW_SHOWMAXIMIZED;
}
SetWindowPlacement(hwnd, &windowPlacement);
When this code executes, if maximized is TRUE, the window is set to the size of a maximized window, but the maximize/restore button is still a maximize button, not a restore button.
I've tried using the ShowWindow() function with the same results.
It turns out the WM_CREATE message handler was the wrong place to do this. After moving the code out of the window procedure and into the wWinMain() function after the call to CreateWindow() but before the call to ShowWindow(), it works as expected.

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 - Changing dialog item focus programmatically

I have a Modeless dialog which shows a bunch of buttons; some of these are customized to draw stuff with GDI.
Now, when the user clicks on a customized one under certain conditions, a message box appears to alert user of the error and this is fine.
The problem is that after accepting the Message Box (showed as MB_ICON_ERROR), everywhere I click in the dialog, I always get the error message as if the whole dialog send the message to the customized button and the only way to get rid this is to press tab and give the focus to another control.
This is a strange behaviour and knowing why happens wouldn't be bad, but a simple workaround for now should do the job.
Since the moment that is probably a matter of focus, I've tried to set it on another control (in the owner dialog) by doing:GetDlgItem( IDC_BTN_ANOTHER_BUTTON )->SetFocus();
and then, inside the customized control by adding:KillFocus( NULL );but had no results.
How should I use these functions?
Thanks in advance.
PS: if I comment the AfxMessageBox, the control does not show this bizarre behaviour.
EDITI'll show some code as requested.
// This is where Message Box is popping out. It is effectively inside the dialog code.
void CProfiloSuolaDlg::ProcessLBtnDownGraphProfilo(PNT_2D &p2dPunto)
{
// m_lboxProfiles is a customized CListBox
if(m_lboxProfiles.GetCurSel() == 0)
{
// This profile cannot be modified.
/*
CString strMessage;
strMessage.Format( _T("Default Profile cannot be edited.") );
AfxMessageBox( strMessaggio, MB_ICONERROR );
*/
return;
}
// Selecting a node from sole perimeter.
SelectNodo(p2dPoint);
}
Actually, the message is commented to keep the dialog working.
// This is inside the customization of CButton
void CMyGraphicButton::OnLButtonDown(UINT nFlags, CPoint point)
{
PNT_2D p2dPunto;
CProfiloSuolaDlg* pDlg = (CProfiloSuolaDlg*)GetParent();
m_pVD->MapToViewport(point,p2dPunto);
switch(m_uType)
{
case GRF_SEZIONE:
pDlg->ProcessLBtnDownGraphProfilo(p2dPunto);
break;
case GRF_PERIMETRO:
pDlg->ProcessLBtnDownGraphPerimetro(p2dPunto);
break;
}
CButton::OnLButtonDown(nFlags, point);
}
Since you are handling the button down event in the button handler for the custom control, you don't need to call the base class. Just comment out CButton::OnLButtonDown(nFlags, point).

How to send a double click message to the specified listview element

How can I send a double click message to the specified listview element in Windows? I know that i need to use SendMessage function, but I'm not sure about an arguments to this function. Can you give me an example, please?
How to fake a NM_DBLCLK notification:
#include <Commctrl.h>
// ensure those variables are ok
HWND hWndListViewParent;
INT iListViewID;
HWND hWndListView;
[...]
NMITEMACTIVATE nmia;
nmia.hdr.code = NM_DBLCLK;
nmia.hdr.hwndFrom = hWndListView;
nmia.hdr.idFrom = iListViewID;
// set up the rest of NMITEMACTIVATE
[...]
SendMessage( hWndListViewParent, WM_NOTIFY, (WPARAM)iListViewID, (LPARAM)&nmia );
I don't think you can do that cross process, however. Try it. If that indedd doesn't work, you will have to fake mouse action via SendInput, or maybe use UIAutomation.

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

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.