Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 406
  • Last Modified:

Monitor EDIT control

I have an EDIT control, and during the entire execution of my program, I need to monitor this field to see if the number "7" was entered.

It doesn't matter what the final value of the EDIT control is, I just need to know if at ANY time, a 7 was entered.

Can someone show me a code snippet example?

Thank you
0
edvinson
Asked:
edvinson
  • 7
  • 5
1 Solution
 
jkrCommented:
You could use a Windows hook (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632589%28v=vs.85%29.aspx) for that which monitors keypress events and checks if they occurred in your edit control, e.g. like

#include <windows.h>

HHOOK g_hhk;
HWND g_hEdit;

LRESULT CALLBACK GetMsgProc(
    int code,
    WPARAM wParam,
    LPARAM lParam
)
{
    if (o > code || PM_NOREMOVE == wParam) return CallNextHookEx(g_hhk,code,wParam,lParam);

    MSG* pmsg = (MSG*) lParam;

    if (pmsg->message == WM_KEYDOWN) { // this one is for us

        if (pmsg->hwnd == g_hEdit && pmsg->wParam == VK_7) { // '7' has been pressed if the monitored edit control

            // ---> ACTION!
        }
    }

    return CallNextHookEx(g_hhk,code,wParam,lParam);
}

void InitMonitoring(HWND hEdit) {

    h_hEdit = hEdit;

    g_hhk = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,NULL,GetCurrentThreadId());
}

void StopMonitoring() {

    UnhookWindowsHookEx(g_hhk);
}

Open in new window

0
 
edvinsonAuthor Commented:
Wow thanks! I just don't know where to implement it, could you show me so I can test it?
Was your code intended to be used in a Dialog based app?


Here is my complete source code:

#include <windows.h>


#include "resource.h"


//---------------------------------------------------------------------------
HWND hWnd;
LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
//---------------------------------------------------------------------------

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow)
{
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1),
	          hWnd, reinterpret_cast<DLGPROC>(DlgProc));

	return FALSE;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch(Msg)
	{
	case WM_INITDIALOG:
		return TRUE;

	case WM_COMMAND:
		switch(wParam)
		{
		case IDOK:
             
			EndDialog(hWndDlg, 0);
			
			
			
			
			return TRUE;
		}
		break;
	}

	return FALSE;
}
//---------------------------------------------------------------------------
                                  

Open in new window


Maybe we can just show a messagebox when the 7 is pressed so I can test.

Thanks
0
 
edvinsonAuthor Commented:
almost forgot, let's use IDC_EDIT1 as my textfield we are monitoring, ok?

Thank you. I am currently blindly trying to put your code into my project, but I am new to c++
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
jkrCommented:
You could do that in any kind of app, all you need the window handle of the control. E.g. like

InitMonitoring(GetDlgItem(IDC_EDIT1));

Open in new window

0
 
edvinsonAuthor Commented:
I feel stupid, you have clearly explained this, but I cannot get this to compile.

Could you show me exactly where to put your working code in the code sample I posted above, please?
0
 
jkrCommented:
What compier errors are you getting?
0
 
jkrCommented:
One thing, that should be a '0' instead of an 'o' in

    if (o > code || PM_NOREMOVE == wParam) return CallNextHookEx(g_hhk,code,wParam,lParam);

Open in new window


i.e.

    if (0 > code || PM_NOREMOVE == wParam) return CallNextHookEx(g_hhk,code,wParam,lParam);

Open in new window

0
 
jkrCommented:
OK, along with your code, that should be

#include <windows.h>


#include "resource.h"

HHOOK g_hhk;
HWND g_hEdit;

LRESULT CALLBACK GetMsgProc(
    int code,
    WPARAM wParam,
    LPARAM lParam
)
{
    if (0 > code || PM_NOREMOVE == wParam) return CallNextHookEx(g_hhk,code,wParam,lParam);

    MSG* pmsg = (MSG*) lParam;

    if (pmsg->message == WM_KEYDOWN) { // this one is for us

        if (pmsg->hwnd == g_hEdit && pmsg->wParam == VK_7) { // '7' has been pressed if the monitored edit control

            // ---> ACTION!
        }
    }

    return CallNextHookEx(g_hhk,code,wParam,lParam);
}

void InitMonitoring(HWND hEdit) {

    h_hEdit = hEdit;

    g_hhk = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,NULL,GetCurrentThreadId());
}

void StopMonitoring() {

    UnhookWindowsHookEx(g_hhk);
}
                                            


//---------------------------------------------------------------------------
HWND hWnd;
LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
//---------------------------------------------------------------------------

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow)
{
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1),
	          hWnd, reinterpret_cast<DLGPROC>(DlgProc));

	return FALSE;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch(Msg)
	{
	case WM_INITDIALOG:
                InitMonitoring(hwndDlg);
		return TRUE;

	case WM_COMMAND:
		switch(wParam)
		{
		case IDOK:
             
			EndDialog(hWndDlg, 0);
			
			
			
			
			return TRUE;
		}
		break;
	}

	return FALSE;
}
//---------------------------------------------------------------------------
                                  
                                            

Open in new window

0
 
jkrCommented:
Oops, sorry - my bad, that should be

#include <windows.h>


#include "resource.h"

HHOOK g_hhk;
HWND g_hEdit;

LRESULT CALLBACK GetMsgProc(
    int code,
    WPARAM wParam,
    LPARAM lParam
)
{
    if (0 > code || PM_NOREMOVE == wParam) return CallNextHookEx(g_hhk,code,wParam,lParam);

    MSG* pmsg = (MSG*) lParam;

    if (pmsg->message == WM_KEYDOWN) { // this one is for us

        if (pmsg->hwnd == g_hEdit && pmsg->wParam == VK_7) { // '7' has been pressed if the monitored edit control

            // ---> ACTION!
        }
    }

    return CallNextHookEx(g_hhk,code,wParam,lParam);
}

void InitMonitoring(HWND hEdit) {

    h_hEdit = hEdit;

    g_hhk = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,NULL,GetCurrentThreadId());
}

void StopMonitoring() {

    UnhookWindowsHookEx(g_hhk);
}
                                            


//---------------------------------------------------------------------------
HWND hWnd;
LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
//---------------------------------------------------------------------------

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow)
{
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1),
	          hWnd, reinterpret_cast<DLGPROC>(DlgProc));

	return FALSE;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch(Msg)
	{
	case WM_INITDIALOG:
                InitMonitoring(GetDlgItem(hwndDlg,IDC_EDIT1));
		return TRUE;

	case WM_COMMAND:
		switch(wParam)
		{
		case IDOK:
             
			EndDialog(hWndDlg, 0);
			
			
			
			
			return TRUE;
		}
		break;
	}

	return FALSE;
}
//---------------------------------------------------------------------------
                                  
                                            
                                            

Open in new window

0
 
edvinsonAuthor Commented:
That is great. Thank you. One final question, if I wanted to monitor multiple controls, should I simply use:

InitMonitoring(GetDlgItem(hwndDlg,IDC_EDIT1));
InitMonitoring(GetDlgItem(hwndDlg,IDC_EDIT2));
InitMonitoring(GetDlgItem(hwndDlg,IDC_EDIT3));

etc? Or would you suggest I rewrite your code to handle multiple controls?
0
 
jkrCommented:
Yes, multiple controls would require that to be rewritte, albeit not that differently - you'd basically make that

void InitMonitoring(HWND* phEdit, size_t count);

Open in new window


and store the handles in an array that you later evaluate inside 'GetMsgProc()' (also changing 'g_hEdit' to an array/pointer).
0
 
sarabandeCommented:
if you have a dialog form where the edit control is part of, it is easier to handle the EN_CHANGE notification for the edit control rather than hooking. hooking is the way if you don't own the control or don't have access to the dialog (sources).

WM_COMMAND 
wNotifyCode = HIWORD(wParam); // notification code 
wID = LOWORD(wParam);         // item, control, or accelerator identifier 
hwndCtl = (HWND) lParam;      // handle of control

Open in new window


EN_CHANGE 
idEditCtrl = (int) LOWORD(wParam); // identifier of edit control 
hwndEditCtrl = (HWND) lParam;      // handle of edit control

Open in new window



when using mfc you simply could add an event handler in the resource editor. select the edit control and choose 'add event handler' from right-click menu. or you override the PreTranslateMessage function of your mfc dialog class and check for WM_KEYDOWN message (similar as done in the hook).

when not using mfc go to the windows proc of your dialog and handle WM_COMMAND message.

case WM_COMMAND:
{
     WORD wNotifyCode = HIWORD(wParam); // notification code 
     WORD idEdit = LOWORD(wParam); 
     if (wNotifyCode == EN_CHANGE && idEdit == IDC_EDIT1)
     {
          char szEdit[256] = { '\0' };
          HWND hwndEdit = (HWND) lParam;
          GetWindowText( hwndEdit, szEdit, sizeof(szEdit));
          if (strchr(szEdit, '7')) 
          {
               // string contains '7'
               DWORD dwStart;
               DWORD dwEnd;
               wParam = (WPARAM) (LPDWORD) &dwStart; // receives starting position 
               lParam = (LPARAM) (LPDWORD) &dwEnd;   // receives ending position 
               SendMessage(hwndEdit, EM_GETSEL, wParam, lParam);
               if (dwStart == dwEnd && dwStart >= 0 && dwStart <= (DWORD)strlen(szEdit))
               { 
                    if (szEdit[dwStart] == '7')
                    {
                         // 7 was entered at caret (cursor) position
                    }
               }
         }
}

Open in new window



note, the code checking for the actual change would become easier if you save old value of edit control. then you only have to compare old value with new value to find out whether a '7' was entered.

note, if you use EN_UPDATE instead of EN_CHANGE the notification was sent before the edit control was displayed. you then can prevent the '7' to be displayed by calling SetWindowText.

Sara
0
 
edvinsonAuthor Commented:
Thank you both so much! Sara, as always, I appreciate your thorough explanations and code examples.

JKR, I am attempting to re-write to accommodate multiple controls. Thanks again.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 7
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now