• Welcome to Valhalla Legends Archive.
 

[C++/Win32] Catching Enter key in EDIT control

Started by Okee, July 12, 2005, 11:24 PM

Previous topic - Next topic

Okee

This more or less pertains to the Win32 UI aspect of VC++ and bots, more so than it did to C++ which is why I'm asking in the Bot Dev forum.

Anyways, I have an EDIT control on my main dialog, for sending text to bnet. I guess I'm looking for the WM_CHAR message from it, and also either the HIWORD, or LOWORD of the wParam to be 13 - for Enter key. Right now I'm looking at the LOWORD of wParam, in the WM_COMMAND message.

My question is, how to I detect enter key so I can send the text? I don't seem to be receiving any messages when I hit the enter key. I had a switch statement with a default case creating a messagebox with the wParam values and it wouldn't create a message box when I hit enter. I would for other keys though. Any help?

Thanks guys.

UserLoser.


Okee

I'm not quite sure what you mean by subclassing an edit box. Either way wouldn't I have to, at some point, catch these messages anyways?

UserLoser.

#3
In your subclassed editbox WindowProc callback function you will see all these messages you will need to handle such as WM_CHAR, WM_KEYUP, WM_KEYDOWN.  Then I'd suggest checking wParam on WM_KEYUP message for it being VK_RETURN, then using GetWindowText, grab the editbox text and send it away.

See SetWindowLong, CallWindowProc, GetWindowText, SetWindowText - those will all be necessary here.

warz

To subclass an instance of a window, call the SetWindowLong function and specify the handle to the window to subclass the GWL_WNDPROC flag and a pointer to the subclass procedure. SetWindowLong returns a pointer to the original window procedure; use this pointer to pass messages to the original procedure. The subclass window procedure must use the CallWindowProc function to call the original window procedure.

The following example shows how to subclass an instance of an edit control in a dialog box. The subclass window procedure enables the edit control to receive all keyboard input, including the ENTER and TAB keys, whenever the control has the input focus.


WNDPROC wpOrigEditProc;

LRESULT APIENTRY EditBoxProc(
    HWND hwndDlg,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam)
{
    HWND hwndEdit;

    switch(uMsg)
    {
        case WM_INITDIALOG:
            // Retrieve the handle to the edit control.
            hwndEdit = GetDlgItem(hwndDlg, ID_EDIT);

            // Subclass the edit control.
            wpOrigEditProc = (WNDPROC) SetWindowLong(hwndEdit,
                GWL_WNDPROC, (LONG) EditSubclassProc);
            //
            // Continue the initialization procedure.
            //
            return TRUE;

        case WM_DESTROY:
            // Remove the subclass from the edit control.
            SetWindowLong(hwndEdit, GWL_WNDPROC,
                (LONG) wpOrigEditProc);
            //
            // Continue the cleanup procedure.
            //
            break;
    }
    return FALSE;
        UNREFERENCED_PARAMETER(lParam);
}

// Subclass procedure
LRESULT APIENTRY EditSubclassProc(
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam)
{
    if (uMsg == WM_GETDLGCODE)
        return DLGC_WANTALLKEYS;

    return CallWindowProc(wpOrigEditProc, hwnd, uMsg,
        wParam, lParam);
}


Found on MSDN.

Okee

This is the same thing as how I was doing it - only that it isolates all the windows messages into one SubProc it seems.

Anywho, heres my sub proc for the edit window


LRESULT APIENTRY EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_GETDLGCODE)
        return DLGC_WANTALLKEYS;

switch(wParam) {
default:
{
MessageBoxFmt(hwnd, MB_OK, "d", "%d", LOWORD(wParam));
break;
}
}

    return CallWindowProc(hwndEditProc, hwnd, uMsg, wParam, lParam);
}


Now, I checked wParam for WM_KEYUP, WM_KEYDOWN, WM_CHAR, etc, but it never makes a message box when i tell it to in its own switch case. How do I make it do something when the enter key is pushed here? Sorry, I've been checking the HIWORD, and LOWORD of wParam for the past few hours, and have been looking all over MSDN also.

Thanks.

Kp

I'm too tired to examine your code in depth, but a couple of quick comments:

First, warz's answer is not 64bit clean.  Use SetWindowLongPtr and GWLP_WNDPROC for 64bit cleanliness (with Microsoft-supplied preprocessor definitions to make your code continue to work when compiled for 32bit mode).

Second, if you can't find the problem in your code, try having it log msg,wparam,lparam to a file or the console, then press Enter in your edit control and see what pops up.  If you can't discern the meaning of the output you get, post it here and someone else can probably pick it apart.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Okee

Here's my current code:


case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BNSENDCHATBUTTON:
{
switch(HIWORD(wParam))
{
case WM_KEYDOWN:
{
AppendText(hBNChat, WHITE, "WM_KEYDOWN\n");
break;
}
default:
{
AppendText(hBNChat, WHITE, "%d\n", HIWORD(wParam));
break;
}
}
break;
}
                                [...]


Now, it prints WM_KEYDOWN when I initially click on the EDIT box, giving it focus. If it already has focus it doesnt print WM_KEYDOWN. When I press keys it doesnt print WM_KEYDOWN. When I press any button it prints 1024 and then 768. When I press enter it doesnt print anything.

Anyone know why? :-\

dxoigmn

Quote from: Okee on July 14, 2005, 06:57 PM
Here's my current code:


case IDC_BNSENDCHATBUTTON:


Anyone know why? :-\

Either your variable is horribly named or it seems appropriate that the message would be sent to the edit control and not a button?

Okee

Sorry, it was just named poorly. It is my edit box though. I still can't seem to capture the Enter key.

warz

I see what you're trying to do. Keep in mind though that when you hit enter the WM_COMMAND message will be sent to your form not to that edit control. Inside the WM_COMMAND message will be the id of any default button on the form to be pressed. Assuming you have no "send" button, or any default button, the id of the button will be "IDOK" by default. so in your case statements dont look for the controls name in WM_COMMAND, look for IDOK.

Okee

#11
Thanks, I'm catching the Enter key now, and calling a function to manipulate my Edit control contents. All it does though is beep when I hit enter.


void DoSendText(void) {
char SendText[200];
AppendText(hBNChat, WHITE, "%d\n", szLocalAccountInfo.Connected);
if(szLocalAccountInfo.Connected == true) {
AppendText(hBNChat, WHITE, "a\n");
GetWindowText(GetDlgItem(hMainDlg, IDC_BNSEND), SendText, sizeof(SendText));
SetWindowText(GetDlgItem(hMainDlg, IDC_BNSEND), "");
} else {
AppendText(hBNChat, RED, "Not connected\n");
GetWindowText(GetDlgItem(hMainDlg, IDC_BNSEND), SendText, sizeof(SendText));
SetWindowText(GetDlgItem(hMainDlg, IDC_BNSEND), "");
}
}


It's weird - it'll print the value of Connected, which is 0, not connected and remove the text when I hit enter before I connect, but after I connect all it does it beep. It won't remove the text, or print "a" or print the Connected value.

Anyone know why?

Okee

Update: I think I'm going to just add a send button, and make it non-visible so whenever IDOK is processed it'll have a default button to push. For some reason I still can't get it to do anything once it's connected. The bot just beeps and doesn't let me modify the contents of the edit box.