Solved

Monitor EDIT control

Posted on 2013-05-25
13
397 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
  • 7
  • 5
13 Comments
 
LVL 86

Expert Comment

by:jkr
Comment Utility
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
Comment Utility
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
Comment Utility
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
 
LVL 86

Expert Comment

by:jkr
Comment Utility
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
Comment Utility
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
Comment Utility
What compier errors are you getting?
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 86

Expert Comment

by:jkr
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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 32

Expert Comment

by:sarabande
Comment Utility
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
Comment Utility
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
std::atomic with custom class 6 149
C++ get user from AD  (VS6) 7 47
Dynamically allocate memory 9 46
Best book to learn C++ 4 52
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now