I'd like to implemented a window that its top coordinate is always X (for simplicity let's say 0). Meaning, the window's top side is fixed on 0 which is the top of the screen.
I've already implemented the window, set its position using SetWindowPos but I'm struggling maintaining its top coordinate value.
You can create a window with no caption bar, for example
CreateWindow(className, title, WS_THICKFRAME | WS_POPUP, ...)
Then override WM_NCHITTEST to change the requests for moving the window up and down.
If window has caption bar, for example:
CreateWindow(className, title, WS_OVERLAPPEDWINDOW, ...)
Then add override for WM_WINDOWPOSCHANGING as well:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_NCHITTEST:
{
LRESULT lresult = DefWindowProc(hwnd, msg, wParam, lParam);
switch (lresult)
{
case HTTOP: lresult = HTCLIENT; break;
case HTTOPLEFT: lresult = HTLEFT; break;
case HTTOPRIGHT: lresult = HTRIGHT; break;
}
return lresult;
}
case WM_WINDOWPOSCHANGING:
{
WINDOWPOS* wndpos = (WINDOWPOS*)lParam;
wndpos->y = 100;//choose a fixed position
break;
}
...
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Related
Is there a way to automatically/by default set the mouse cursor to point inside a newly created window (using for e.g. the CreateWindow function)? I know that for keyboard input there is a SetFocus() function, but haven't found a similar function for a mouse.
As #IInspectable said, the following is the code implementation.
LRESULT CALLBACK WndProcNOP(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
RECT rcClient;
GetWindowRect(hwnd, &rcClient);
int x = rcClient.left + (rcClient.right - rcClient.left) / 2;
int y = rcClient.top + (rcClient.bottom - rcClient.top) / 2;
SetCursorPos(x, y);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
return 0;
}
I try to change standart WndProc function. I have this code:
HWND btn = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_CLIENTEDGE, L"BUTTON", L"Window title", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON
, 50, 50, 50, 50, (HWND)XApplicationMainWindow->window->_wnd, (HMENU)123,
(HINSTANCE)GetWindowLongPtr(XApplicationMainWindow->window->_wnd, GWLP_HINSTANCE), NULL);
SetWindowLongPtrW(btn, GWLP_WNDPROC, (LONG_PTR)SubclassWindowProc);
I can use L"BUTTON" class name, but when I change WndProc function I'll have a problem.
On this picture, you can see the blank square and normal button. If I try to create new WNDCLASS or WNDCLASSEX, I'll have nothing... Why?
How can I change the standart WndProc function, if I use L"BUTTON" class name?
It's my second WndProc:
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
break;
case WM_COMMAND:
//Event click
switch (LOWORD(wParam))
{
case 123:
OutputDebugStringA("Subclass click2");
break;
default:
break;
}
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
DefWindowProc() is the wrong window procedure for your SubclassWindowProc() to be calling.
You need to call the previous window procedure that you are replacing - the window procedure that handles all of the button's default behaviors (like drawing the button so it actually looks like a button, and responding to user input like a button, etc). SetWindowLongPtr() returns a pointer to that procedure to you, but you are currently ignoring it.
See Subclassing Controls on MSDN for more details.
Try this instead:
WNDPROC btnWndProc;
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_COMMAND:
//Event click
switch (LOWORD(wParam))
{
case 123:
OutputDebugStringA("Subclass click2");
break;
}
break;
}
return CallWindowProc(hWnd, btnWndProc, uMsg, wParam, lParam);
}
...
HWND btn = CreateWindowEx(...);
btnWndProc = (WNDPROC) SetWindowLongPtrW(btn, GWLP_WNDPROC, (LONG_PTR)SubclassWindowProc);
Alternatively, using SetWindowSubclass(), which is safer than using SetWindowsLongPtr(), eg:
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
switch (uMsg) {
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, SubclassWindowProc, uIdSubclass);
break;
case WM_COMMAND:
//Event click
switch (LOWORD(wParam))
{
case 123:
OutputDebugStringA("Subclass click2");
break;
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
...
HWND btn = CreateWindowEx(...);
SetWindowSubclass(btn, SubclassWindowProc, 1, 0);
Now, that being said, your subclass will never call OutputDebugStringA(), because it will never receive the WM_COMMAND message you are expecting. When a button is clicked, a WM_COMMAND message is not sent to the button itself. The button posts a WM_COMMAND message to the button's parent window instead (in this case, to XApplicationMainWindow->window->_wnd). So, you need to handle the WM_COMMAND message in the window procedure of the parent window, not in the window procedure of the button itself.
Otherwise, if you still want to subclass the button itself, you will have to handle the WM_LBUTTON(DOWN|UP) and WM_KEY(DOWN|UP)/WM_CHAR messages that the button receives and then subsequently translates into a WM_COMMAND message for its parent window.
I'm making a buttons in a main window ( hwnd ) that when you click on a button it opens new window ( hwndSec ) that can be controlled by the main window !
when i click on a button, the hwndSec showed up ! and while i'm clicking on the other buttons it can be modified ... but when i close it and attempt to reopen it again it doesn't response ! so the buttons become useless !
This a simple example of a single button just to open the window then trying to open it again.
The setting i set for hwndSec:
wincl.hInstance = hInstance;
wincl.lpszClassName = "HwndSecClass";
wincl.lpfnWndProc = WindowProcedureSec;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wincl))
return 0;
hwnd = CreateWindowEx (
0,
wincl.lpszClassName,
_T("Window 2"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
500,
HWND_DESKTOP,
NULL,
hInstance,
NULL
);
i make two window procedures :
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WindowProcedureSec (HWND, UINT, WPARAM, LPARAM);
when i click a button i call this fonction :
ShowWindow(hwndSec,SW_SHOW);
and then the second window appear normally , when i close the window it doesn't came back to appear again.
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
CreateWindow("BUTTON",
"open",
WS_CHILD | WS_VISIBLE ,
200,100,
100,50,
hwnd,
(HMENU) ID_BUTTON,
NULL,
NULL);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_BUTTON :
//printf("%s",(char*)GetLastError());
ShowWindow(hwndSec,SW_SHOW);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WindowProcedureSec (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
{
case WM_DESTROY:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
When a window is being closed, it receives a WM_CLOSE message. If that message is passed to DefWindowProc(), the default behavior is to destroy the window:
An application can prompt the user for confirmation, prior to destroying a window, by processing the WM_CLOSE message and calling the DestroyWindow function only if the user confirms the choice.
By default, the DefWindowProc function calls the DestroyWindow function to destroy the window.
This is further discussed on MSDN:
Closing the Window
So, you will have to re-create your secondary window with CreateWindow/Ex() each time you want to show it after it has been closed:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
...
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_BUTTON :
if (!hwndSec)
{
hwndSec = CreateWindowEx(
0,
_T("HwndSecClass"),
_T("Window 2"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
500,
HWND_DESKTOP,
NULL,
hInstance,
NULL
);
}
ShowWindow(hwndSec, SW_SHOW);
break;
}
break;
...
}
return 0;
}
LRESULT CALLBACK WindowProcedureSec (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
hwndSec = NULL;
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
If you don't want to do that, then you need to make the secondary window handle the WM_CLOSE message and not pass it to DefWindowProc(). For instance, call ShowWindow(SW_HIDE) instead, and then you can later call ShowWindow(SH_SHOW) when needed
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
...
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_BUTTON :
ShowWindow(hwndSec, SW_SHOW);
break;
}
break;
...
}
return 0;
}
LRESULT CALLBACK WindowProcedureSec (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
ShowWindow(hwnd, SW_HIDE);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
I would like to hide a caret from a RichEdit(50W) with ES_READONLY style specified.
It's pretty confusing for the user, when the caret is blinking and the user can't type.
I tried to hide the caret using HideCaret() function,
however it doesn't work for me with following code:
LRESULT CALLBACK ChatMessaegsSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) // Subclassed control
{
LRESULT ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
switch(msg)
{
//Also tried with EN_SETFOCUS
case WM_SETFOCUS:
{
ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
HideCaret(ChatMessages); //Returns 5 (Access denied.)
break;
}
//According the documentation:
//If your application calls HideCaret five times in a row,
//it must also call ShowCaret five times before the caret is displayed.
case WM_KILLFOCUS: //The message is called when the RichEdit get focus, however nothing happens.
{
ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
ShowCaret(ChatMessages);
break;
}
}
return ret;
}
Here is the solution:
LRESULT CALLBACK ChatMessaegsSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LRESULT ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
switch(msg)
{
case WM_LBUTTONDOWN:
{
HideCaret(ChatMessages);
break;
}
case WM_KILLFOCUS:
{
ShowCaret(ChatMessages);
break;
}
}
return ret;
}
NOTE this only works when user induces the focus with mouse. Therefore if anyone knows how to deal with it correctly, feel free to answer, I'll be glad.
I am trying to Subclass the Listbox and the Edit Control of a Combobox for some customasing reasons. Below is the code work . Subclassing for Edit Control is working perfect but Listbox is not getting the messeage of MouseDown.
void Subclass(HWND hComboBox)
{
HWND hEdit=FindWindowEx(hComboBox, NULL, WC_EDIT, NULL);
HWND hCombo=FindWindowEx(hComboBox, NULL, WC_LISTBOX, NULL);
SetProp(hEdit, TEXT("Wprc"), (HANDLE)GetWindowLongPtr(hEdit, GWL_WNDPROC));
SubclassWindow(hEdit, ComboBox_Proc);
SetProp(hCombo, TEXT("Wprc1"), (HANDLE)GetWindowLongPtr(hCombo, GWL_WNDPROC));
SubclassWindow(hCombo, ComboBox_Proc1);
}
static LRESULT CALLBACK ComboBox_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CHAR:
break;
case WM_KEYDOWN:
break;
case WM_DESTROY:
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (DWORD)GetProp(hwnd, TEXT("Wprc")));
RemoveProp(hwnd, TEXT("Wprc"));
break;
default:
return CallWindowProc((WNDPROC)GetProp(hwnd, TEXT("Wprc")), hwnd, msg, wParam, lParam);
}
return FALSE;
}
static LRESULT CALLBACK ComboBox_Proc1(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
//PROBLEM IS HERE
break;
case WM_DESTROY:
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (DWORD)GetProp(hwnd, TEXT("Wprc1")));
RemoveProp(hwnd, TEXT("Wprc1"));
break;
default:
return CallWindowProc((WNDPROC)GetProp(hwnd, TEXT("Wprc1")), hwnd, msg, wParam, lParam);
}
return FALSE;
}
The ListBox part of a ComboBox is of type COMBOLBOX (with L).
The ComboLBox window is not a child of the ComboBox window.
The only way I found to subclass the COMBOLBOX control is as follows.
Windows sends the WM_CTLCOLORLISTBOX message to the COMBOBOX (no L) before the listbox is drawn. The lParam of this message contains the handle of the listbox.
case WM_CTLCOLORLISTBOX:
{
if ( !hSubclassedListBox )
{
hSubclassedListBox = (HWND)lParam;
SubclassWindow(hSubclassedListBox , MyLBProc);
}
}
Alsoo see this link for more information
For those who are using Visual Studio with WINVER set to 0500 or higher (Windows XP or later), you can use the GetComboBoxInfo function (passing the handle to the ComboBox), which will return (in a COMBOBOXINFO structure) the handles to both the Edit box and the ComboLBox (ListBox). The handles can then be used to get the CWnd-derived objects they represent.