Solved

Monitor EDIT control

Posted on 2013-05-25
13
402 Views
Last Modified: 2013-05-27
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
Comment
Question by:edvinson
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
13 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 39197877
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
 
LVL 1

Author Comment

by:edvinson
ID: 39198345
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
 
LVL 1

Author Comment

by:edvinson
ID: 39198347
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
Technology Partners: 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!

 
LVL 86

Expert Comment

by:jkr
ID: 39198355
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
 
LVL 1

Author Comment

by:edvinson
ID: 39198364
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
 
LVL 86

Expert Comment

by:jkr
ID: 39198366
What compier errors are you getting?
0
 
LVL 86

Expert Comment

by:jkr
ID: 39198370
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
 
LVL 86

Expert Comment

by:jkr
ID: 39198373
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
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 39198376
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
 
LVL 1

Author Closing Comment

by:edvinson
ID: 39198383
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
 
LVL 86

Expert Comment

by:jkr
ID: 39198387
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
 
LVL 34

Expert Comment

by:sarabande
ID: 39199291
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
 
LVL 1

Author Comment

by:edvinson
ID: 39200225
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

Secure Your Active Directory - April 20, 2017

Active Directory plays a critical role in your company’s IT infrastructure and keeping it secure in today’s hacker-infested world is a must.
Microsoft published 300+ pages of guidance, but who has the time, money, and resources to implement? Register now to find an easier way.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
SetCurrentDirectory path limit 7 144
c++, dynamic object by json 1 60
Why  my code (program) build with old compiler? 11 106
No module found pypyodbc, 3 43
Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question