Hey, I was working on a program in windows API where there are multiple edit boxes and there are push buttons. If a pushbutton is clicked, I want the program to find the edit box that the cursor is in and add the character to that edit box. Now I know how to add the character to the box but I don't know how to determine which edit box that the cursor is in. Any Help?
Frederick2 189 Posting Whiz
Yea, try this...
GetFocus The GetFocus function retrieves the handle to the window that has the keyboard focus, if the
window is associated with the calling thread's message queue.
HWND GetFocus(VOID)
Parameters This function has no parameters.
Return Values
The return value is the handle to the window with the keyboard focus. If the calling thread's message
queue does not have an associated window with the keyboard focus, the return value is NULL.
Remarks
Even if GetFocus returns NULL, another thread's queue may be associated with a window that has the keyboard focus.
Use the GetForegroundWindow function to retrieve the handle to the window with which the user is currently working. You can associate your thread's message queue with the windows owned by another thread by using the AttachThreadInput function.
Edited by Frederick2 because: n/a
goody11 -2 Junior Poster
Ok, I tried this but it didn't work.
case IDC_AWA:
{
HWND hRetrieve = GetFocus();
int length = GetWindowTextLength(hRetrieve);
LPCSTR pszText = "á";
SendMessage(hRetrieve, EM_SETSEL, length, length + 1);
SendMessage(hRetrieve, EM_REPLACESEL, true,(LPARAM) pszText);
}
Frederick2 189 Posting Whiz
Ahh! goody, sorry about that! You are right. It doesn't work. I'm afraid the solution is a bit more complex. Basically, when a textbox has the focus and you click some other control such as a button, the edit control will lose the keyboard focus and windows will send it a WM_KILLFOCUS event just before it changes the focus to whatever. The problem with that is that in order for you to intercept that WM_KILLFOCUS message received by the edit control just about to lose the keyboard focus, you need to have subclassed the edit control itself (the window procedure of edit controls is in Windows). I wrote a quick PowerBASIC program to test out my theory and it worked perfectly. I put a button at the top of the Form, and generated five or six edit controls within a for loop in the WM_CREATE handler. Within that for loop I subclassed all the edit controls. Within the subclass proc I tested for WM_KILLFOCUS messages. When I got one I stored the handle of the edit control receiving a WM_KILLFOCUS message at offset zero within four extra .cbWndExtra bytes I allocated in the main Window's class structure. When you click the button at the top of the form a text string is written to whatever of the six edit controls had the focus befoire you clicked the button. Here is the PowerBASIC SDK style code. If you are an Api coder it will be quite clear to you, as the general structure of WinMain and WndProc() as well as everything else is about the same. Sorry its not in C++ code. If you don't understand it I'll redo it in C++. It would probably take me a half hour or so, and its Sunday afternoon, and my wife wants me to go to the store for groceries. Believe me though, I tried it and it works great.
#Compile Exe
#Include "Win32api.inc"
%IDC_BUTTON = 1250
%IDC_EDIT = 1251
Global fnOldEditProc As Dword
Function fnNewEditProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
Select Case As Long wMsg
Case %WM_KILLFOCUS
Call SetWindowLong(GetParent(hWnd),0,hWnd)
fnNewEditProc=0
End Select
fnNewEditProc=CallWindowProc(fnOldEditProc,hWnd,wMsg,wParam,lParam)
End Function
Function WndProc(Byval hWnd As Long,Byval wMsg As Long,Byval wParam As Long,Byval lParam As Long) Export As Long
Select Case wMsg
Case %WM_CREATE
Local hButton As Dword,hEdit As Dword
Local hIns As Dword
Register i As Long
hIns=GetModuleHandle(Byval 0)
hButton=CreateWindow("button","Button #1",%WS_CHILD Or %WS_VISIBLE,85,20,100,25,hWnd,%IDC_BUTTON,hIns,0)
For i=0 To 5
hEdit=CreateWindowEx(%WS_EX_CLIENTEDGE,"edit","",%WS_CHILD Or %WS_VISIBLE Or %WS_BORDER,10,70+40*i,250,25,hWnd,%IDC_EDIT+i,hIns,Byval 0)
fnOldEditProc=SetWindowLong(hEdit,%GWL_WNDPROC,CodePtr(fnNewEditProc))
Next i
WndProc=0
Exit Function
Case %WM_COMMAND
Select Case Lowrd(wParam)
Case %IDC_BUTTON
Local szString As Asciiz*64
szString="SetWindowText() Put This Here!"
Call SetWindowText(GetWindowLong(hWnd,0),szString)
End Select
WndProc=0
Exit Function
Case %WM_DESTROY
Call PostQuitMessage(0)
WndProc=0
Exit Function
End Select
WndProc=DefWindowProc(hWnd, wMsg, wParam, lParam)
End Function
Function Winmain(Byval hIns As Long, Byval hPrev As Long, Byval lpCL As Asciiz Ptr, Byval iS As Long) As Long
Local Msg As tagMsg
Local winclAss As WndClAssEx
Local szAppName As Asciiz * 32
Local hWnd As Dword
szAppName="StrangeBehavior"
winclAss.lpszClAssName=Varptr(szAppName)
winclAss.lpfnWndProc=Codeptr(WndProc)
winclAss.cbSize=Sizeof(winclAss)
winclAss.style=%CS_HREDRAW Or %CS_VREDRAW
winclAss.cbClsExtra=0
winclAss.cbWndExtra=4
winclAss.hInstance=hIns
winclAss.hIcon=LoadIcon(%NULL, Byval %IDI_APPLICATION)
winclAss.hCursor=LoadCursor(%NULL, Byval %IDC_ARROW)
winclAss.hbrBackground=%COLOR_BTNFACE+1
winclAss.lpszMenuName=%NULL
winclAss.hIconSm=0
RegisterClAssEx winclAss
hWnd=CreateWindow(szAppName,"Caption = Form28",%WS_OVERLAPPEDWINDOW,200,100,280,350,0,0,hIns,Byval 0)
Call ShowWindow(hWnd,iS)
Call UpdateWindow(hWnd)
While GetMessage(Msg,%NULL,0,0)
TranslateMessage Msg
DispatchMessage Msg
Wend
Function=msg.wParam
End Function
Frederick2 189 Posting Whiz
Felt bad about providing a solution in another language in a C++ forum, so here it is in C++. First the include, then Main.cpp. There are about five edit controls. Set the focus in one of them, then click the button at top.
//WinTypes.h
#ifndef WINTYPES_H
#define WINTYPES_H
typedef struct WindowsEventArguments
{
HWND hWnd;
WPARAM wParam;
LPARAM lParam;
HINSTANCE hIns;
}WndEventArgs, *lpWndEventArgs;
struct EVENTHANDLER
{
unsigned int Code;
long (*fnPtr)(lpWndEventArgs);
};
#endif
//Main.cpp - GoodysProblem
#include <windows.h>
#include <tchar.h>
#include "WinTypes.h"
#define BTN_BUTTON1 2000
#define IDC_EDIT 3000
EVENTHANDLER EventHandler[3];
WNDPROC fnOldEditProc;
long __stdcall fnEditSubClass(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
if(msg==WM_KILLFOCUS) //This procedure is a 'sub class 'hook'
{ //into the internal 'edit' class window
SetWindowLong(GetParent(hwnd),0,(long)hwnd); //procedure within windows. Its purpose
return 0; //is to 'hook' WM_KILLFOCUS messages. When
} //it gets one it persists it to the main
//window's .cbWndExtra bytes.
return CallWindowProc(fnOldEditProc,hwnd,msg,wParam,lParam);
}
long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
HWND hCtl;
Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
hCtl=CreateWindow
(
_T("button"),
_T("Button #1"),
WS_CHILD | WS_VISIBLE,
70,20,150,30,
Wea->hWnd,
(HMENU)(BTN_BUTTON1),
Wea->hIns,
NULL
);
for(unsigned int i=0;i<6;i++)
{
hCtl=CreateWindowEx
(
WS_EX_CLIENTEDGE,
_T("edit"),
_T(""),
WS_CHILD|WS_VISIBLE,
10,70+40*i,265,25,
Wea->hWnd,
(HMENU)(IDC_EDIT+i),
Wea->hIns,
0
);
fnOldEditProc=
(WNDPROC)SetWindowLong
(
hCtl,
GWL_WNDPROC,
(LONG)fnEditSubClass
);
}
return 0;
}
long fnWndProc_OnCommand(lpWndEventArgs Wea) //When you press the button the text below is put
{ //in the edit control whose hWnd is stored at offset
switch(LOWORD(Wea->wParam)) //zero in the .cbWndExtra bytes. It got put there
{ //when one of the edit controls lost focus as picked
case BTN_BUTTON1: //up in the sub class proc.
SetWindowText((HWND)GetWindowLong(Wea->hWnd,0),_T("This Edit Control Just Lost Focus!"));
break;
}
return 0;
}
long fnWndProc_OnClose(lpWndEventArgs Wea)
{
if(MessageBox(Wea->hWnd,_T("Do You Wish To Exit This App?"),_T("Exit Check?"),MB_YESNO)==IDYES)
{
DestroyWindow(Wea->hWnd);
PostQuitMessage(WM_QUIT);
}
return 0;
}
long __stdcall fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
WndEventArgs Wea;
for(unsigned int i=0;i<3;i++)
{
if(EventHandler[i].Code==msg)
{
Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam; //less crap).
return (*EventHandler[i].fnPtr)(&Wea);
}
}
return (DefWindowProc(hwnd,msg,wParam,lParam));
}
void AttachEventHandlers(void) //This procedure is called from WinMain() and associates
{ //Windows messages with the procedure to handle them.
EventHandler[0].Code=WM_CREATE, EventHandler[0].fnPtr=fnWndProc_OnCreate;
EventHandler[1].Code=WM_COMMAND, EventHandler[1].fnPtr=fnWndProc_OnCommand;
EventHandler[2].Code=WM_CLOSE, EventHandler[2].fnPtr=fnWndProc_OnClose;
}
int __stdcall WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
TCHAR szClassName[]=_T("StrangeBehavior");
WNDCLASSEX wc;
MSG messages;
HWND hWnd;
AttachEventHandlers();
wc.lpszClassName=szClassName; wc.lpfnWndProc=fnWndProc;
wc.cbSize=sizeof (WNDCLASSEX); wc.style=CS_DBLCLKS;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION); wc.hInstance=hIns;
wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION); wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW; wc.cbWndExtra=4;
wc.lpszMenuName=NULL; wc.cbClsExtra=0;
RegisterClassEx(&wc);
hWnd=CreateWindow(szClassName,_T("StrangeBehavior"),WS_OVERLAPPEDWINDOW,200,100,300,360,HWND_DESKTOP,0,hIns,0);
ShowWindow(hWnd,iShow);
while(GetMessage(&messages,NULL,0,0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
Edited by Frederick2 because: Shorten Some Lines That Were Too Long.
goody11 -2 Junior Poster
I'm having troubles implementing your code into mine. I used resource files to create my buttons and edit boxes and I'm not using the window for this, I'm just using a dialog box here is some of my code.
The resource file:
IDD_MAIN2 DIALOG DISCARDABLE 0, 0, 650, 151
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Spanish Word Editor"
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_STEXT,0,7,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ETEXT,60,7,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_POSTEXT,120,7,50,14,ES_AUTOHSCROLL
LTEXT "Conjugations(only if verb is the Part of speech)",IDC_STATIC,25,21,150,8
LTEXT "Present Present Progressive Preterite Imperfect Past Progressive Future Conditional Present Subjunctive Imperfect Subjunctive",IDC_STATIC,78,35,600,8;
LTEXT "Yo",IDC_STATIC,0,49,150,8
LTEXT "Tú",IDC_STATIC,0,63,150,8
LTEXT "Usted/Él/Ella",IDC_STATIC,0,77,150,8
LTEXT "Nosotros",IDC_STATIC,0,91,150,8
LTEXT "Vosotros",IDC_STATIC,0,105,150,8
LTEXT "Ustedes/Ellos/Ellas",IDC_STATIC,0,119,150,8
EDITTEXT IDC_YOTEXT,65,47,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_TUTEXT,65,61,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ELTEXT,65,75,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_NOSTEXT,65,89,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_VOSTEXT,65,103,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ELLOSTEXT,65,117,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PPYOTEXT,130,47,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PPTUTEXT,130,61,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PPELTEXT,130,75,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PPNOSTEXT,130,89,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PPVOSTEXT,130,103,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PPELLOSTEXT,130,117,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PYOTEXT,195,47,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PTUTEXT,195,61,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PELTEXT,195,75,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PNOSTEXT,195,89,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PVOSTEXT,195,103,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PELLOSTEXT,195,117,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_IYOTEXT,260,47,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ITUTEXT,260,61,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_IELTEXT,260,75,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_INOSTEXT,260,89,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_IVOSTEXT,260,103,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_IELLOSTEXT,260,117,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PAPYOTEXT,325,47,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PAPTUTEXT,325,61,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PAPELTEXT,325,75,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PAPNOSTEXT,325,89,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PAPVOSTEXT,325,103,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PAPELLOSTEXT,325,117,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_FYOTEXT,390,47,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_FTUTEXT,390,61,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_FELTEXT,390,75,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_FNOSTEXT,390,89,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_FVOSTEXT,390,103,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_FELLOSTEXT,390,117,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_CYOTEXT,455,47,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_CTUTEXT,455,61,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_CELTEXT,455,75,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_CNOSTEXT,455,89,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_CVOSTEXT,455,103,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_CELLOSTEXT,455,117,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PSYOTEXT,520,47,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PSTUTEXT,520,61,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PSELTEXT,520,75,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PSNOSTEXT,520,89,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PSVOSTEXT,520,103,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_PSELLOSTEXT,520,117,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ISYOTEXT,585,47,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ISTUTEXT,585,61,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ISELTEXT,585,75,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ISNOSTEXT,585,89,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ISVOSTEXT,585,103,50,14,ES_AUTOHSCROLL
EDITTEXT IDC_ISELLOSTEXT,585,117,50,14,ES_AUTOHSCROLL
PUSHBUTTON "á",IDC_AWA,200,133,12,12
PUSHBUTTON "é",IDC_EWA,212,133,12,12
PUSHBUTTON "í",IDC_IWA,224,133,12,12
PUSHBUTTON "ó",IDC_OWA,236,133,12,12
PUSHBUTTON "ú",IDC_UWA,248,133,12,12
PUSHBUTTON "ñ",IDC_NWT,260,133,12,12
PUSHBUTTON "¿",IDC_UQ,272,133,12,12
PUSHBUTTON "¡",IDC_UE,284,133,12,12
PUSHBUTTON "&Save",IDC_SAVE,585,133,50,14
END
and here is the dialog procedure that corresponds with it in the .cpp file:
BOOL CALLBACK DlgProc2(HWND hwnd2, UINT Message2, WPARAM wParam2, LPARAM lParam2)
{
switch(Message2)
{
case WM_INITDIALOG:
// This is where we set up the dialog box, and initialise any default values
SetDlgItemText(hwnd2, IDC_STEXT, " Spanish");
SetDlgItemText(hwnd2, IDC_ETEXT, " English");
SetDlgItemText(hwnd2, IDC_POSTEXT, "Part of Speech");
break;
case WM_COMMAND:
switch(LOWORD(wParam2))
{
case IDC_AWA:
{
int length = GetWindowTextLength(hRetrieve);
LPCSTR pszText = "á";
SendMessage(hRetrieve, EM_SETSEL, length, length + 1);
SendMessage(hRetrieve, EM_REPLACESEL, true,(LPARAM) pszText);
}
break;
case IDC_EWA:
{
HWND edit = GetDlgItem(hwnd2, IDC_ANSQW);
int length = GetWindowTextLength(edit);
LPCSTR pszText = "é";
SendMessage(edit, EM_SETSEL, length, length + 1);
SendMessage(edit, EM_REPLACESEL, true,(LPARAM) pszText);
}
break;
case IDC_IWA:
{
HWND edit = GetDlgItem(hwnd2, IDC_ANSQW);
int length = GetWindowTextLength(edit);
LPCSTR pszText = "í";
SendMessage(edit, EM_SETSEL, length, length + 1);
SendMessage(edit, EM_REPLACESEL, true,(LPARAM) pszText);
}
break;
case IDC_OWA:
{
HWND edit = GetDlgItem(hwnd2, IDC_ANSQW);
int length = GetWindowTextLength(edit);
LPCSTR pszText = "ó";
SendMessage(edit, EM_SETSEL, length, length + 1);
SendMessage(edit, EM_REPLACESEL, true,(LPARAM) pszText);
}
break;
case IDC_UWA:
{
HWND edit = GetDlgItem(hwnd2, IDC_ANSQW);
int length = GetWindowTextLength(edit);
LPCSTR pszText = "ú";
SendMessage(edit, EM_SETSEL, length, length + 1);
SendMessage(edit, EM_REPLACESEL, true,(LPARAM) pszText);
}
break;
case IDC_NWT:
{
HWND edit = GetDlgItem(hwnd2, IDC_ANSQW);
int length = GetWindowTextLength(edit);
LPCSTR pszText = "ñ";
SendMessage(edit, EM_SETSEL, length, length + 1);
SendMessage(edit, EM_REPLACESEL, true,(LPARAM) pszText);
}
break;
case IDC_UQ:
{
HWND edit = GetDlgItem(hwnd2, IDC_ANSQW);
int length = GetWindowTextLength(edit);
LPCSTR pszText = "¿";
SendMessage(edit, EM_SETSEL, length, length + 1);
SendMessage(edit, EM_REPLACESEL, true,(LPARAM) pszText);
}
case IDC_SAVE:
DoFileSave(hwnd2);
EndDialog(hwnd2, 0);
hwndGoto = NULL;
break;
}
break;
case WM_CLOSE:
EndDialog(hwnd2, 0);
hwndGoto = NULL;
break;
default:
return FALSE;
}
return TRUE;
}
Frederick2 189 Posting Whiz
Hope somebody else can help you with that Goody. I simply don't use the Windows Dialog Engine at all. I'm not absolutely sure, but I believe the same general principals will be involved as in the code I showed. Basically, when you click a button in a window (whether it be a CreateWindowEx() window or a window created by the Windows Dialog Engine), the focus will be transferred from the edit box with focus, to the button. This activity is a complex one in that it involves many messages. First you'll have various mouse messages sent to the button. Then you'll have various kill focus & set focus messages. None of these are going to occur within your dialog procedures, and only by utilizing these messages will you be able to accomplish what you described you want to accomplish. So, if you insist on continuing what you are trying to do, you are going to have to find out how you are going to do it within the framework you have chosen to use, and that appears to be the Windows Dialog Engine.
In my opinion use of Dialog Boxes for major and complicated user interfaces - esapecially ones involving extremely unusual behavior such as you are trying to implement, is a very bad idea. While the code I provided might seem complicated, it is my opinion that if you ever achieve this within the framework of the Windows Dialog Engine, your final code will be much, much worse. All I can say is perhaps someone more familiar with Dialog boxes can show you a better way to do it.
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.