I am writing a MFC program in which I have a a lot of Editboxes and I want to get all their text values and put them in a container. How can I achieve this without writing a line for each ID. I'm using this code for each ID:
CEdit *edit;
edit = reinterpret_cast<CEdit *>(GetDlgItem(IDC_NAME1));
But if I use that method I would have to write it 45 times. That doesn't seem right.
Is there a way of getting all the Editboxes in a container so I can use them that way or something like that?
You can certainly create an array (or other container) or pointers to CEdit: CEdit edits[45]; If the values of IDC_NAME1 through IDC_NAME45 are contiguous, you can just do something like:
for (int i=0; i<45; i++)
names[i] = reinterpret_cast<CEdit *>(GetDlgItem(IDC_NAME1 + i));
If those identifiers may not be contiguous, then you can put them in an array, and just index into that array as needed.
One caution: unless they're something like a grid of otherwise nearly identical edit controls, 45 on a screen may well be a bit much. If they are like a grid, you might want to look at one of the many available grid controls instead.
You do not have to use controls IDs.
Use EnumChildWindows and get test only for edit controls. Snippet follows.
Add following in dialog’s header:
afx_msg LRESULT OnFoundEdit(WPARAM wParam, LPARAM lParam);
And this to cpp:
#define WM_U_FOUND_EDIT WM_APP + 0x100
BEGIN_MESSAGE_MAP(CEditCtrlFishingDlg, CDialog)
ON_MESSAGE(WM_U_FOUND_EDIT, OnFoundEdit)
.
.
.
.
END_MESSAGE_MAP()
Write this line in the place you want to start edit text collection:
EnumChildWindows(m_hWnd, EnumChildProc, (LPARAM)m_hWnd);
Enum child procedure:
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
CString csBuffer;
LPTSTR pBuf = csBuffer.GetBufferSetLength(MAX_PATH);
GetClassName(hwnd, pBuf, MAX_PATH);
csBuffer.ReleaseBuffer();
if(!csBuffer.CompareNoCase(_T("edit")))
{
SendMessage((HWND)lParam, WM_U_FOUND_EDIT, 0, (LPARAM)hwnd);
}
return TRUE;
}
and the handler:
LRESULT YourDlg::OnFoundEdit(WPARAM wParam, LPARAM lParam)
{
CWnd *pWnd = FromHandle((HWND)lParam);
CString csTxt;
pWnd->GetWindowText(csTxt);
// do what you need with text here
return 0;
}
Related
I recently started coding in C++ and I am very new to it. (I code in Javascript, PHP, Java and Obj-C more often)
I'm practicing how to hook a message box and change its position. This is what I have in my .cpp file (after reading this SO post).
#include <iostream>
#pragma comment(lib,"User32.lib")
#include <windows.h>
HHOOK hhookCBTProc = 0;
LRESULT CALLBACK pfnCBTMsgBoxHook(int nCode, WPARAM wParam, LPARAM lParam){
if (nCode == HCBT_CREATEWND)
{
CREATESTRUCT *pcs = ((CBT_CREATEWND *)lParam)->lpcs;
if ((pcs->style & WS_DLGFRAME) || (pcs->style & WS_POPUP))
{
HWND hwnd = (HWND)wParam;
SetWindowPos(hwnd, HWND_TOP,130,122, 0, 0,SWP_NOSIZE);
}
}
return (CallNextHookEx(hhookCBTProc, nCode, wParam, lParam));
}
int main(void)
{
hhookCBTProc = SetWindowsHookEx(WH_CBT,pfnCBTMsgBoxHook,
0, GetCurrentThreadId());
int sResult = MessageBox ( NULL, "Hooked!", "oh my", MB_OK );
UnhookWindowsHookEx(hhookCBTProc);
return 0;
}
For some reason the position of the message box isn't changing. Where did it go wrong?
(I know I can create a customized window or dialog. But I am doing it this way because I want to learn how to hook a message box and where I did wrong.)
Firstly you should check in the debugger that your hook is actually being called, if you haven't already.
Secondly, at the time the HCBT_CREATEWND hook event is triggered, the window has only just been created - the system has yet to size and position it. It will do this with the values in the CREATESTRUCT after the hook returns - overriding your SetWindowPos call.
See the docs from MSDN on the lParam value for this particular hook event:
Specifies a long pointer to a CBT_CREATEWND structure containing
initialization parameters for the window. The parameters include the
coordinates and dimensions of the window. By changing these
parameters, a CBTProc hook procedure can set the initial size and
position of the window.
Therefore, the correct way to use this hook to change a window's position is to modify the values in the CREATESTRUCT directly.
Also note that it's quite possible that the dialog manager sizes and positions the window after creation, so if you find that this still isn't working for you, you may need to try watching for the HCBT_MOVESIZE event instead.
From the docs
At the time of the HCBT_CREATEWND notification, the window has been
created, but its final size and position may not have been determined
and its parent window may not have been established.
Maybe try hooking into CBT_ACTIVATE instead.
I want to change the size of the tabs.
We have added a closing cross to our tabs, but it conflicts spaciously with the text of the tab.
So far I have realized the following:
GetItemRect(int i, RECT* rc) gives me the rect. What I really would like is a SetItemRect.
SetItem cannot be used as the item does not contain its size. It is calculated based upon the contents I give it.
I could add a space char in the end of the string, but that's just against the natural order of things. I will not tweak pixels with CStrings.
SetSize is supposed to set the size of a tab (all tabs?). But I cannot find out where to put it that does not trigger a redraw, which sparks an infinite loop if I put it with the WM_PAINT case.
This is where I custom draw the contents of the tab, but I cannot resize them here:
LRESULT CSkinnedTabCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_PAINT: {
...
CPaintDC dc(this);
INT nCount = GetItemCount();
for (INT i = 0; i < nCount; i++) {
CRect rc;
GetItemRect(i, rc);
DrawItem(dc, i, rc);
}
return TRUE;
}
Where do I set the size of the tabs, and how?
IIRC you need to overwrite WM_NCCALCSIZE message.
I am writing my first simple program in C++/WINAPI, with a lot of check boxes and a few edit fields, which will set up some calculations on a button press. All of my check boxes work/store info through individual cases, ie
switch (msg)
{
...
case WM_COMMAND:
{
switch (wParam)
{
case IDBC_BoxCheck1:
{...}
case IDBC_BoxCheck2:
{...}
...
} ...
...but I assumed edit fields didn't work as a case statement like a button press, since the value has to be read at the end once it has been changed as many times as the user wants. I looked online and attempted to use the SendMessage(hwnd, ...) and GetWindowText(hwnd, ...) functions to send a WM_GETTEXT command to the edit field and store it to a lpstr string, but I ran into the same problem with both of them - the hwnd for the edit fields aren't declared in the scope where the WM_GETTEXT command is being sent from, and I'm not sure how to get it there. Here is an overview of the structure being used in my program, which comes from a mix of some tutorials I was working with:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
return OnCreate(hwnd, reinterpret_cast<CREATESTRUCT*>(lParam));
// OnCreate is a sub function that handles the creation of all the buttons/controls,
// since there are so many of them, with the format:
// HWND editControl1 = CreateControl(...); // CreateControl being another sub fnct
// that creates edit field ctrls
// editControl1 is the hwnd I'm trying
// to read the value from
// HWND checkControl1 = CreateButton(...); // Creates button ctrls, including ck box
...
}
...
case WM_COMMAND:
{
switch (wParam)
{
case IDBC_BoxCheck1: // These control IDs are defined at the top of the file
{
LPSTR Check1;
StoreInfo(Check1); // Just a sub fnct to store info for later calculations
}
case IDBC_BoxCheck2:
{
LPSTR Check2;
StoreInfo(Check2);
} // etc... there are 20 or so check boxes/buttons
case IDBC_Calculate:
{
LPSTR edit1;
GetWindowText(editControl1, edit1, 100); // or SendMessage(editControl1, ...)
// This kicks out the error of editControl1 not being declared in this scope
StoreInfo(edit1);
// Calculation function goes here
} ...
} ....
}
default: DefWindowProc(hwnd, msg, wParam, lParam);
}
}
IDBC_Calculate is the final button pressed before the calculations run. I figured the best place to read and store the values from the edit fields would be after this button is pressed, right before the calculation function is called, but tied to the same command. This is where the hwnd editControl1 is undefined, but I don't know how to send the definition to this scope, or where else I should be reading and storing the edit field values.
Any help or pointers on getting the values from these edit fields to my other functions would be appreciated! I've seen many different ways to check button states in various tutorials/lessons, so I'd love to know if there's a better way to do what I've written above in general.
Your edit fields have IDs right? Then you can use GetDlgItem.
editControl1 = GetDlgItem(hwnd, CONTROL_ID_1);
GetDlgItem is badly named, it doesn't just work in dialog boxes. It gets the handle of any child window from a parent window, using the ID of the child window.
And what Anders K says is correct. The way you are using GetWindowText will crash your program.
So far i have been using GetClassName() to get a window handle with the class name that interested me while enumerating with EnumChildProc() but right now i am in situation where plenty of HWND's use the same classname so only way to identify my window i assume would be with its name which is unique.
So while i am enumerating i was thinking to use something like...
If getwindowname() == what i need... but i have no idea what function can i use for this, is there a function like getwindowname() that i can use in this enumeration?
GetWindowText ?
this.. worked
TCHAR winname[MAX_PATH];
long lenght;
HWND hwndineed;
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {
lenght = SendMessage(hwnd, WM_GETTEXT, 99, (LPARAM)winname);
if(wcscmp(winname, _T("caption i needed")) == 0)
{
hwndineed= hwnd;
return FALSE; // end enumeration
}
}
I have a win 32 application written in c++ which sets the low level keyboard hook. now i want to sendInput to any app like word / notepad. how do i do this?
i have already done enough of using findwindow / sendmessage. for all these, i need to know edit controls. finding the edit control is very difficult.
since SendInput works for any windows application, i want to use it. the problem is i get a call to my callback function with the pressed key.
for e.g i pressed A and i want to send U+0BAF unicode character to the active applciation windows. in this case, assume it is notepad.
the problem is i get two characters U+0BAF and A in the notepad.
A is being sent because i am calling CallNextHookEx( NULL, nCode, wParam, lParam);
if i return 1 after sendInput, then nothing is sent to notepad.
any suggestion?
If I understood your problem correctly, you should ignore "injected" key events in your hook procedure, like this:
LRESULT CALLBACK
hook_proc( int code, WPARAM wParam, LPARAM lParam )
{
KBDLLHOOKSTRUCT* kbd = (KBDLLHOOKSTRUCT*)lParam;
// Ignore injected events
if (code < 0 || (kbd->flags & LLKHF_INJECTED)) {
return CallNextHookEx(kbdhook, code, wParam, lParam);
}
...
Update: additionally, you have to eat characters and notify some other routine for a character press through Windows messages.
Example:
...
// Pseudocode
if (kbd->vkCode is character) {
if (WM_KEYDOWN == wParam) {
PostMessage(mainwnd, WM_MY_KEYDOWN, kbd->vkCode, 0);
return 1; // eat the char, ie 'a'
}
}
return CallNextHookEx(kbdhook, code, wParam, lParam);
And, in some other module, you handle WM_MY_KEYDOWN:
ie, #define WM_MY_KEYDOWN (WM_USER + 1)
and call the appropriate routine that will generate new key events.