-
Window Button
I have created a window that has 2 edit controls and 1 push button. One edit control is a multiline edit control and the other is a single line edit control. I would like to make it so that when the user is typing in text in the single line edit control and pushes enter, the push button is pressed. When I press enter it seems nothing happens, even if I am not entering text in the single line edit control.
By the way I am not using a dialog box, its a regular window.
Does anyone know how to do this? Thanks.
- Sean
-
Are you using MFC or WINAPI?
Its important to understand that edit controls and buttons are all child windows and have to have the input focus to accept keyboard input. Please answer the above question and we will continue the discussion, their are a couple ways to proceed.
-
I am using Win API. I know that in a dialog window when you press enter it is just like pressing the default button. I am trying to do the same thing here only I am not using a dialog window.
- Sean
-
Thats because dialog boxes send the input focus to the default button by default. One way to do this is have your main window check for the WM_KILLFOCUS message and upon recieving that message place itself back in focus by using SetFocus(hwnd) (handle to main window). Then check the message queue for the enter key, and if pressed send message to button, if not send message to text controls. Note, you will have to keep track of what child window has the input focus.
Edit:
Out of curtousy to the user, I would also through in a check to ensure the mouse is within your window before immediately resetting focus to your program.
-
If you are using a standard SDK app, you can try using SetWindowLong(), this can add another Window Procedure to sit on top of the edit control procedure provided by the framework....then use this to read the WM_KEYDOWN & WM_KEYUP and filter for VK_RETURN....then do whatever processing applicable.....
If you are using MFC, the derive a class from CEdit, add the extra code and use it instead
-
Traveller, I have set the focus to the button and then tried hitting enter, but it is not being pressed. I have then tried clicking on it to make sure it is working and then again tried hitting enter and it still will not work.
Fordy, I have been looking up some things on subclassing in Petrolds book. Can you give me a quick example using the edit control because Petrold uses a different control and does something different. I am using the Win API.
Currently, what I have done is edit my WinMain message loop like this:
Code:
while(GetMessage(&Msg, NULL, 0, 0) > 0){
if(Msg.message==WM_KEYDOWN&&LOWORD(Msg.wParam)==VK_RETURN){
SendMessage(hButtonTalk, BM_CLICK, 0, 0);
continue;
}
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
The reason I added the continue in there is because the single line edit control was making the default error sound when I pressed enter. It seems to work, but I was wondering if there was a better way to do it. Thanks.
- Sean
-
Would you mind posting your code?
-
This is the main source file. There are some other header files as well.
Code:
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <merlin.h>
#include "Global.h"
#include "Main.h"
#include "Menu.h"
#include "Turingres.h"
HINSTANCE ghInstance = NULL;
HWND hwndMain = NULL;
LPSTR gClassName = "TurningMachineClass";
HWND hEditLog = NULL;
HWND hEditInput = NULL;
HWND hButtonTalk = NULL;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
MSG Msg;
ghInstance = hInstance;
if(RegisterWindow()==FAILURE){
return 1;
}
if(CreateMainWindow(nCmdShow)==FAILURE){
return 1;
}
while(GetMessage(&Msg, NULL, 0, 0) > 0){
if(Msg.message==WM_KEYDOWN&&LOWORD(Msg.wParam)==VK_RETURN){
SendMessage(hButtonTalk, BM_CLICK, 0, 0);
continue;
}
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
UnregisterClass(gClassName, ghInstance);
return Msg.wParam;
}
int static RegisterWindow(void){
InitCommonControls();
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.lpfnWndProc = WndMainProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = ghInstance;
wc.hIcon = LoadIcon(NULL, IDI_QUESTION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 11);
wc.lpszMenuName = NULL;
wc.lpszClassName = gClassName;
wc.hIconSm = NULL;
if(RegisterClassEx(&wc)==0){
ERRBOX(ERR_TITLE, ERR_REG);
return FAILURE;
}
return SUCCESS;
}
int static CreateMainWindow(int nCmdShow){
hwndMain = CreateWindowEx(WS_EX_CLIENTEDGE,
gClassName, WND_TITLE,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
WND_WIDTH, WND_HEIGHT,
NULL, NULL, ghInstance, NULL);
if(hwndMain == NULL){
ERRBOX(ERR_TITLE, ERR_WND);
return FAILURE;
}
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
return SUCCESS;
}
LRESULT CALLBACK WndMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch(msg)
{
case WM_CREATE:
CreateControls(hwnd);
CreateMenus(hwnd);
break;
case WM_CLOSE:
CloseProgram(hwnd);
break;
case WM_SIZE:
ResizeWindow(hwnd);
break;
case WM_SETFOCUS:
SetFocus(hEditInput);
break;
case WM_COMMAND:
switch(LOWORD(wParam)){
case BN_CLICKED:
if((HWND)lParam==hButtonTalk){
TalkPressed(hwnd);
}
break;
case MENU_FILE_EXIT:
CloseProgram(hwnd);
break;
case MENU_HELP_VERSION:
DisplayVersion();
break;
case MENU_HELP_HELP:
case MENU_HELP_ABOUT:
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
void static CreateControls(HWND hwnd){
HFONT hFont = CreateFont(FONT_HEIGHT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FONT_NAME);
hEditLog = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "EDIT", "",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_LEFT | ES_READONLY | ES_WANTRETURN,
0, 0, WND_WIDTH-10, WND_HEIGHT-100, hwnd, NULL, ghInstance, NULL);
hEditInput = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_LEFT,
0, WND_HEIGHT-90, WND_WIDTH-50, 25, hwnd, NULL, ghInstance, NULL);
hButtonTalk = CreateWindowEx(WS_EX_CONTROLPARENT, "BUTTON", "Talk",
WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
WND_WIDTH-30, WND_HEIGHT-90, 50, 25, hwnd, NULL, ghInstance, NULL);
if(hEditLog==NULL||hEditInput==NULL||hFont==NULL){
ERRBOX(ERR_TITLE, ERR_CHILD_WND);
CloseProgram(hwnd);
}
SendMessage(hEditLog, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
SendMessage(hEditInput, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
}
void static CreateMenus(HWND hwnd){
HMENU hMenu;
HMENU hSubMenu;
hMenu = CreateMenu();
hSubMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
AppendMenu(hSubMenu, MF_STRING, MENU_FILE_EXIT, "E&xit");
hSubMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help");
AppendMenu(hSubMenu, MF_STRING, MENU_HELP_HELP, "&Contents");
AppendMenu(hSubMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSubMenu, MF_STRING, MENU_HELP_VERSION, "&Version");
AppendMenu(hSubMenu, MF_STRING, MENU_HELP_ABOUT, "&About");
SetMenu(hwnd, hMenu);
}
void static DisplayVersion(void){
char Buffer[1024];
sprintf(Buffer, "%s\nCompiled on %s at %s",MSG_VERSION, __DATE__, __TIME__);
MSGBOX("Information", Buffer);
}
void static ResizeWindow(HWND hwnd){
RECT Wnd;
RECT EditLog;
RECT EditInput;
RECT Button;
int WndHeight = 0;
int WndLegnth = 0;
int ButtonLegnth = 0;
int ButtonHeight = 0;
GetWindowRect(hwnd, &Wnd);
GetWindowRect(hEditLog, &EditLog);
GetWindowRect(hEditInput, &EditInput);
GetWindowRect(hButtonTalk, &Button);
WndHeight = Wnd.bottom-Wnd.top;
WndLegnth = Wnd.right-Wnd.left;
ButtonHeight = Button.bottom-Button.top;
ButtonLegnth = Button.right-Button.left;
SetWindowPos(hEditLog, NULL, 0, 0, WndLegnth-10, WndHeight-85, SWP_NOZORDER);
SetWindowPos(hEditInput, NULL, 0, WndHeight-80, WndLegnth-(ButtonLegnth+20), 25, SWP_NOZORDER);
SetWindowPos(hButtonTalk, NULL, (WndLegnth-ButtonLegnth-15), WndHeight-80, ButtonLegnth, 25, SWP_NOZORDER);
}
void static TalkPressed(HWND hwnd){
char Buffer[1024];
GetWindowText(hEditInput, Buffer, 1024);
sprintf(Buffer, "%s\r\n", Buffer);
SendMessage(hEditLog, EM_REPLACESEL, FALSE, (long int)Buffer);
SetWindowText(hEditInput, "");
SetFocus(hEditInput);
}
void CloseProgram(HWND hwnd){
DestroyWindow(hwnd);
}
Here are the two header files. I just lumped them together.
Code:
#include <windows.h>
// Macros
#define MSGBOX(title,message) MessageBox(hwndMain, message, title, MB_OK | MB_ICONINFORMATION)
#define ERRBOX(title,message) MessageBox(hwndMain, message, title, MB_OK)
// Basic Declarations
#define TRUE 1
#define FALSE 0
#define SUCCESS TRUE
#define FAILURE FALSE
// Window Creation Information
#define WND_TITLE "Turing Test Window"
#define WND_WIDTH 400
#define WND_HEIGHT 200
// Edit Control Information
#define FONT_HEIGHT 16
#define FONT_NAME "Arial"
// Memory Information
#define DEBUG_MODE TRUE
#define MEM_LOG_FILE "MemLog.txt"
// Chatting Information
#define COMPUTER_NAME "Esha"
// Messages/Error Messages
#define ERR_TITLE "Error"
#define ERR_REG "Could not register window class."
#define ERR_WND "Could not create window."
#define ERR_CHILD_WND "Child window could not be created."
#define ERR_MEM "Memory error."
#define MSG_VERSION "Turing Test Version 0.10"
// Global Prototypes
//Main.c
LRESULT CALLBACK WndMainProc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK WndEditSubProc(HWND,UINT,WPARAM,LPARAM);
void CloseProgram(HWND);
//MemMan.c
HGLOBAL Free(HGLOBAL);
HGLOBAL Memory(ULONG);
void LogMemory(void);
// Global Structures
// Global Variables
extern HINSTANCE ghInstance;
extern HWND hwndMain;
extern LPSTR gClassName;
extern HWND hEditLog;
extern HWND hEditInput;
int static RegisterWindow(void);
int static CreateMainWindow(int);
void static CreateControls(HWND);
void static CreateMenus(HWND);
void static DisplayVersion(void);
void static ResizeWindow(HWND);
void static TalkPressed(HWND);
#define MENU_FILE_EXIT 1500
#define MENU_HELP_HELP 1600
#define MENU_HELP_ABOUT 1601
#define MENU_HELP_VERSION 1602
- Sean
-
Here's an example of catching than def button problem from an edit........
Click Me -------> :)
-
SendMessage(hButtonTalk, BM_CLICK, 0, 0);
shouldn't this be BN_CLICKED?
-
Yeah, summed up (you guys pretty much answered it) just test during the entering of the edit control for the enter button and then take action, which would be the clicking of the button.
-
OK. Thanks for your guys' help.
- Sean
-
Code:
case WM_COMMAND:
switch(LOWORD(wParam))
{
case BN_CLICKED:
should be more like
Code:
case WM_COMMAND:
idControl = GET_WM_COMMAND_ID(wParam,lParam) ;
switch(idControl)
{
case ID_BUTTON:
if (BN_CLICKED == HIWORD(wParam))
as you need to look for the HIWORD (not the LOWORD) to get the BN_CLICKED msg (and not the ctrl ID)
Traveller
SendMessage() with a BM_CLICK (button message 'click') actually ends up as a BN_CLICKED (button notification msg 'clicked') in the callback.
-