How to copy the text from editbox into a string array? - winapi

I am making a win32 api window application project on visual studio 2012.I use a LPWSTR type variable to store my strings described as follow.
LPWSTR MyStringList[3]={L"apple",L"orange",L"watermelon"};
I expect to copy the text from an editbox to one of the strings in MyStringList. Therefore,I made a simple editbox and button.
Here is the definition of editbox and button.
case WM_CREATE:
hEdit = CreateWindow(L"EDIT",
L"",
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
10, 10, 200, 25,
hWnd,
(HMENU)ID_EDIT,
GetModuleHandle(NULL),
NULL);
hBtn = CreateWindow(L"BUTTON",
L"",
WS_CHILD | WS_VISIBLE,
250, 10, 50, 30,
hWnd,
(HMENU)ID_BUTTON,
GetModuleHandle(NULL),
NULL);
Here is the action when the button is pushed.The two messagebox are used to see if the string has been changed after function GetWindowText is called.
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case ID_BUTTON:
MessageBox(hWnd,MystringList[1],L"Before_Pusing",MB_OK);
GetWindowText(hEdit,MystringList[1],sizeof(MystringList[1]));
MessageBox(hWnd,MystringList[1],L"After_Pushing",MB_OK);
InvalidateRect(hWnd,NULL,TRUE);
break;
Now I tried to push the button after typing "banana" into the editbox. The second string "orange" should be replaced with "banana". However,it turned out that nothing changed .The second messagebox displayed "orange" as the first messagebox did. What's wrong with my code? Please help! Thanks a lot!

You could try this, adding whatever programming quirks that Windows needs.
#define MYLEN 20
...
char MyStringList[3][MYLEN+1] = {"apple", "orange", "watermelon"};
Then you can fetch the string from the edit box with
GetWindowText(hEdit,MystringList[1],MYLEN);
Although the GetWindowText() documentation says
"Copies the text of the specified window's title bar (if it has one) into a buffer. If the specified window is a control, the text of the control is copied. However, GetWindowText cannot retrieve the text of a control in another application."

Related

How to prevent moving of a window without titlebar but with WS_SYSMENU style?

I want to prevent moving of a window which I created before using CreateWindowEx.
HWND hWnd = CreateWindowEx(0, wc.lpszClassName, "Title", WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_OVERLAPPEDWINDOW, 0, 0, rect.right - rect.left, rect.bottom - rect.top, nullptr, nullptr, nullptr, nullptr);
The most common solution suggested for this is changing the windows style to have no titlebar i.e.
SetWindowLongPtr(hWnd, GWL_STYLE, GetWindowLongPtr(hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME));
While this solves the problem for drag- & drop at the titlebar, the window is still movable from the control menu (if the window is active press ALT, LEFT, DOWN and select "Move"). I tried using EnableMenuItem(GetSystemMenu(hWnd, FALSE), SC_MOVE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); because this is how the disabling for the Close entry works (using SC_CLOSE instead of SC_MOVE), but it did not disable the Move option.
Is there any way using win32 api to disable only the "Move" option from the context menu without removing the WS_SYSMENU style completly?
The clue to disabling the SC_MOVE item is in the description of the GetSystemMenu function:
The system automatically grays items on the standard window menu, depending on the situation. The application can perform its own checking or graying by responding to the WM_INITMENU message that is sent before any menu is displayed.
So even though you're disabling the menu item initially, the system is re-enabling it when the menu is displayed. To fix it, you need to handle WM_INITMENU or WM_INITMENUPOPUP yourself and override the system's behaviour. For example,
in your window procedure:
case WM_INITMENUPOPUP:
if (wParam == reinterpret_cast<WPARAM>(GetSystemMenu(hWnd, FALSE)))
{
// override handling of the system menu
EnableMenuItem(reinterpret_cast<HMENU>(wParam), SC_MOVE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
return 0;
}
// if WM_INITMENUPOPUP isn't for the system menu, fall through to
// default processing
return DefWindowProc(hWnd, uMsg, wParam, lParam);

Why is my capture window code not working?

I am newbie to winapi. I have seen an example to capture desktop excluding some windows at codeproject
There a child window is created and it is captured.
hwndMag = CreateWindow(WC_MAGNIFIER, TEXT("MagnifierWindow"),
WS_CHILD | MS_SHOWMAGNIFIEDCURSOR | WS_VISIBLE,
0, 0, m_ScreenX, m_ScreenY,
hostDlg->GetSafeHwnd(), NULL, hInstance, NULL );
Instead of creating a child window, I want to create a parent window.
I have tried with this code.
hwndMag = CreateWindow(WC_MAGNIFIER, TEXT("MagnifierWindow"),
MS_SHOWMAGNIFIEDCURSOR | WS_VISIBLE,
0, 0, m_ScreenX, m_ScreenY,
NULL , NULL, hInstance, NULL );
A new window is visible with black screen. And even when I click the capture button the window is stucked.
Why is this happening and How can I make that work with a new parent window?
Thanks
The magnifier window should be a child window. It therefore needs a host parent window. The example code on MSDN shows how to do it:
BOOL CreateMagnifier(HINSTANCE hInstance)
{
// Register the host window class.
WNDCLASSEX wcex = {};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = HostWndProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
wcex.lpszClassName = WindowClassName;
if (RegisterClassEx(&wcex) == 0)
return FALSE;
// Create the host window.
hwndHost = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT,
WindowClassName, WindowTitle,
WS_CLIPCHILDREN,
0, 0, 0, 0,
NULL, NULL, hInstance, NULL);
if (!hwndHost)
{
return FALSE;
}
// Make the window opaque.
SetLayeredWindowAttributes(hwndHost, 0, 255, LWA_ALPHA);
// Create a magnifier control that fills the client area.
hwndMag = CreateWindow(WC_MAGNIFIER, TEXT("MagnifierWindow"),
WS_CHILD | MS_SHOWMAGNIFIEDCURSOR | WS_VISIBLE,
0, 0,
LENS_WIDTH,
LENS_HEIGHT,
hwndHost, NULL, hInstance, NULL );
if (!hwndMag)
{
return FALSE;
}
return TRUE;
}
This same documentation also says:
The magnifier control must be hosted in a window created with the WS_EX_LAYERED extended style. After creating the host window, call SetLayeredWindowAttributes to set the opacity of the host window. The host window is typically set to full opacity to prevent the underlying screen content from showing though. The following example shows how to set the host window to full opacity:
SetLayeredWindowAttributes(hwndHost, NULL, 255, LWA_ALPHA);
If you apply the WS_EX_TRANSPARENT style to the host window, mouse clicks are passed to whatever object is behind the host window at the location of the mouse cursor. Be aware that, because the host window does not process mouse clicks, the user will not be able to move or resize the magnification window by using the mouse.
The MSDN example above illustrates this. And the CodeProject article that you link to also adheres to these rules. You must do likewise.
in case it's of interest, I created a sample app which uses the magnification API a while back called "Windows 7 UI Automation Client API C# sample (focus tracking)", available at https://code.msdn.microsoft.com/Windows-7-UI-Automation-6390614a. The app tracks where keyboard focus is, and then shows the element with focus in a magnification window, (and inverts the colors using the magnification API). This is a C# app, so it uses interop to access the magnification API.
A screenshot of the results is shown below.
Thanks,
Guy

Is it possible to add control to another process's window?

I've created a MFC window and, from another project, I wanted to add a button to that window via its handle (using FindWindow). The handle is correct, but nothing happens. Is this unachievable or am I doing something wrong?
Here's my code:
HWND hWnd = FindWindow(NULL, "MFCtest");
if(hWnd)
{
printf("Found it\n");
HWND hwndButton = CreateWindow(
"BUTTON",
"OK", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
0, // x position
0, // y position
100, // Button width
100, // Button height
hWnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
if(!hwndButton)
printf("GetLastError: %d\n", GetLastError());
}
Yes. BUT!
The problem is that a window always belongs to a thread that creates it. So the messages for such a control messages will arrive in the thread that creates such a window.
This might work, but because messages form the parent window will be sent to the child will take the long way through the message queue and may cause locks if the message can't be retrieved and handled directly.
So at the end I would suggest to: Don't do it!

winapi dialogbox doesn't show

I have the problem with my dialog, that when i invoke the function "DialogBoxA" the Dialog doesn't appear. I only get the "Busy Cursor" and the the cursor is also trapped inside of a small rectangle (the size of the dialog). After the press of (almost) any button it magically appears.
Dialog box call
DialogBoxA(hInstance,MAKEINTRESOURCEA(IDD_ORACLE_DIALOG),0,reinterpret_cast<DLGPROC>(DlgProc));
Dialog resource code
IDD_ORACLE_DIALOG DIALOGEX 0, 0, 155, 71
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,43,50,50,14
PUSHBUTTON "Cancel",IDCANCEL,98,50,50,14
COMBOBOX IDC_COMBOSERVER,53,6,94,30,CBS_DROPDOWN | CBS_SORT | CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
EDITTEXT IDC_EDITLOG,54,25,94,14,ES_AUTOHSCROLL
LTEXT "Server",IDC_STATIC,7,7,47,13
LTEXT "Log",IDC_STATIC,7,25,47,13
END
DialogProc
LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam,LPARAM lParam){
switch(Msg){
case WM_INITDIALOG:
for(auto it = vServerList.begin();it!=vServerList.end();++it){
SendMessageA(GetDlgItem(hWndDlg,IDC_COMBOSERVER),CB_ADDSTRING,0,reinterpret_cast<LPARAM>(it->c_str()));
}
if(vServerList.size()>0){
SendMessage(GetDlgItem(hWndDlg,IDC_COMBOSERVER),CB_SETCURSEL,0,0);
SendMessage(GetDlgItem(hWndDlg,IDC_EDITLOG),WM_NCLBUTTONDOWN,HTCAPTION,0);
}else{
SendMessage(GetDlgItem(hWndDlg,IDC_COMBOSERVER),WM_NCLBUTTONDOWN,HTCAPTION,0);
}
#ifdef _DEBUG
SendMessageA(GetDlgItem(hWndDlg,IDC_EDITLOG),WM_SETTEXT,0,reinterpret_cast<LPARAM>("q40log"));
#endif
return TRUE;
case WM_COMMAND:
switch(wParam){
case IDOK:
size_t tServer,tLog;
tServer = GetWindowTextLength(GetDlgItem(hWndDlg,IDC_COMBOSERVER))+1;
tLog = GetWindowTextLength(GetDlgItem(hWndDlg,IDC_EDITLOG))+1;
char *pszServer,*pszLog;
pszServer = static_cast<char*>(calloc(tServer,sizeof(char)));
pszLog = static_cast<char*>(calloc(tLog,sizeof(char)));
GetDlgItemTextA(hWndDlg,IDC_COMBOSERVER,pszServer,tServer);
GetDlgItemTextA(hWndDlg,IDC_EDITLOG,pszLog,tLog);
szServer = pszServer;
szUser = pszLog;
free(pszServer);
free(pszLog);
EndDialog(hWndDlg,0);
return TRUE;
case IDCLOSE:
case IDCANCEL:
EndDialog(hWndDlg,0);
return FALSE;
}
break;
}
return FALSE;
}
The obvious failure modes are:
The dialog procedure is faulty.
The dialog resource is invalid.
The dialog resource is linked incorrectly and so cannot be loaded.
The instance handle is incorrect.
Of these options, the cast that you used in the dialog procedure parameter, it seems very likely that the dialog procedure is faulty.
I expect that you added the cast because the code would not compile. And it would not compile because the dialog procedure has an incorrect signature. The cast does not change that fact. It is just a way for you to suppress the compiler and tell it that you know better than it does. Generally speaking, the compiler tends to be right. If your dialog procedure has the wrong signature you need to correct it. Refer to the documentation to find out the correct signature.
The other big problem with your code is that you ignore the return value of DialogBox. If the function fails then the documentation tells you that a value of 0 or -1. In that scenario you can call GetLastError to get extended error information. You must get into the habit of checking for errors when using Win32 API functions.

In GetClientRect rect.bottom rect.right not correct

I'm creating a program in which I want to place a button near to bottom-right corner of the Window. I'm using GetClientRect to get top, bottom, right and left of the window. Top and left are working fine but bottom and right are not working. Here's my code:
WNDCLASSEX Program;
/*Class declaration*/
hWndMain = CreateWindowEx (WS_EX_APPWINDOW,
"Program",
"Program",
WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
GetSystemMetrics(SM_CXSCREEN)/2-210,
GetSystemMetrics(SM_CYSCREEN)/2-135,
420,270,
HWND_DESKTOP,
NULL,hInstance,NULL);
//Window Procedure
WM_CREATE:
{
RECT MaxSize;
GetClientRect(hWndMain,&MaxSize);
/*Menu declaration using CreateMenu, AppendMenu etc*/
HWND hCalculate = CreateWindowEx(0,WC_BUTTON,
"Calculate",
WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_DEFPUSHBUTTON | 0x00000001,
MaxSize.right-156,MaxSize.bottom-51,140,30,
hWnd,(HMENU)IDC_BUTTON1,
GetModuleHandle(NULL), 0);
}
After compiling the code and running the program I'm not able to see the button. Please help.
This assignment to hWndMain looks like it's in your mainline code:
hWndMain = CreateWindowEx (WS_EX_APPWINDOW,
While this is in the WndProc:
//Window Procedure
WM_CREATE:
{
...
GetClientRect(hWndMain,&MaxSize);
However, the WM_CREATE message is received and processed within the call to CreateWindow, so it hasn't yet returned and so the assignment to hWndMain hasn't yet taken place. So you're likely calling GetClientRect() with an invalid or NULL hWndMain, and it's likely failing and returning an error which you're ignoring. Instead, use the hwnd parameter that's passed to the WndProc.

Resources