CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Nov 2010
    Posts
    2

    SendMessage to AfxMessageBox

    Hi!

    I'm trying to send a message to an AfxMessageBox. I want to simulate an <OK> button press.
    The reason is, that we are using a scanner to scan an <OK> barcode instead of pressing the <OK> button itself.

    HWND hWnd = ::FindWindowEx(NULL, NULL, _T("#32770"), _T("MyMessageBox"));
    if (hWnd)
    {
    ::SendMessage(hWnd, MyMessage, (WPARAM)0, (LPARAM)0);
    }

    This works when the AfxMessageBox is an MB_OK type and MyMessage is WM_CLOSE.
    If the type is MB_YESNO or others, this does not work. If the messages are others than WM_CLOSE, this does not work.

    I would like to be able to simulate a <YES> button press og <NO> button press for a MB_YESNO MessageBox type.

    Any idears ?

    /Jakob

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: SendMessage to AfxMessageBox

    Try SendInput with VK_RETURN (for default button).
    Or simulate BN_CLICKED notification.
    Victor Nijegorodov

  3. #3
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: SendMessage to AfxMessageBox

    Since you are restricting the message box to AfxMessageBox, you can make certain assumptions with regard to the buttons.

    You know that there will be a minimum of 1 and a max of 3 buttons (including a help button).

    The buttons will always be in the same location, so its 'ordinal' will always be the same.

    I've used the code below to close system dialogs before. In it's day it was very reliable for closing message box dialogs. The method takes a hwnd to the messagebox (or AfxMessageBox) and an enum to the button type.

    Code:
    const LPCTSTR BTN_CLASS = _T("Button");
    
    //+-----------------------------------------------------------------------
    //	Private Helper Method:	FindErrorWindow
    //
    //	Purpose:			Searches the system for this object's error
    //							window.
    //	Restrictions:	
    //					
    //	Parameters:		Parent hWnd (hwnd to the dialog)
    //					enum of buttons
    //					
    //
    //	Return:			Captured window hWnd, NULL if window not found
    //------------------------------------------------------------------------
    void CWindowTrap::HandleButton(HWND hWnd, _BTNType nButton)
    {
    	Tstring sBtnText;
    	Tstring sAltBtnText;
    
    	switch(nButton)
    	{
    	case WTBTN_YES:			sBtnText = _T("&Yes");			sAltBtnText	= _T("Yes");		break;
    	case WTBTN_NO:			sBtnText = _T("&No");			sAltBtnText	= _T("No");			break;
    	case WTBTN_CLOSE:		sBtnText = _T("&Close");		sAltBtnText	= _T("Close");		break;
    	case WTBTN_IGNORE:		sBtnText = _T("&Ignore");		sAltBtnText = _T("Ignore");		break;
    	case WTBTN_OK:			sBtnText = _T("&Ok");			sAltBtnText	= _T("Ok");			break;
    	case WTBTN_CANCEL:		sBtnText = _T("&Cancel");		sAltBtnText = _T("Cancel");		break;
    	case WTBTN_TERMINATE:	sBtnText = _T("&Terminate");	sAltBtnText	= _T("Terminate");	break;
    	case WTBTN_DONT_SEND:	sBtnText = _T("&Don't Send");	sAltBtnText	= _T("Don't Sent");	break;
    	case WTBTN_WMCLOSE:
    		PostMessage(hWnd, WM_CLOSE, 0,0); 
    		return;		// Exit here, no need to click buttons
    	}
    
    	HWND hBtn = ::FindWindowEx(hWnd, NULL, BTN_CLASS, sBtnText.c_str());
    	if (hBtn != NULL)														
    		PostMessage(GetParent(hBtn),WM_COMMAND, GetDlgCtrlID(hBtn),long(hBtn));
    	else
    	{
    		hBtn = ::FindWindowEx(hWnd, NULL, BTN_CLASS, sAltBtnText.c_str());
    		PostMessage(GetParent(hBtn),WM_COMMAND, GetDlgCtrlID(hBtn),long(hBtn));
    	}
    
    
    }
    Notice how GetParent and GetDlgCtrlID are used in conjuction with PostMessage to close the dialog? This is code you'll be able to reuse.

    Now the difference in what you are trying to achieve is that you don't know the button text (i.e. Yes, OK, etc.). The good news is that instead of searching for an exact text match, you can search for the 1st button that is a child of the dialog using FindWindowEx:

    Code:
    hBtn = ::FindWindowEx(hWnd, NULL, BTN_CLASS, NULL);
    Then call PostMessage as before (but be sure to check for errors):
    Code:
    PostMessage(GetParent(hBtn),WM_COMMAND, GetDlgCtrlID(hBtn),long(hBtn));
    The cool thing is that you can actually click on any of the buttons even if you don't know their text.

    To click on the second button, you just use FindWindowEx in a loop until you reach the second ordinal.

    Here's a non-tested code example:

    HWND FindButtonByOrdinal( HWND hWnd, UINT uOrdinal )
    {
    HWND hBtn = NULL, hBtnAfter = NULL;

    do
    {
    hBtn = ::FindWindowEx( hWnd, hBtnAfter, BTN_CLASS, NULL );

    hBtnAfter = hBtn;
    }
    while( hBtn != NULL, && uOrdinal-- > 0 );

    return hBtn;
    }

  4. #4
    Join Date
    Nov 2010
    Posts
    2

    Re: SendMessage to AfxMessageBox

    Thanks a lot for your answer and time spended !! I'll try this.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured