I am trying to find out why my application has a small, few pixel, border.
My understanding is that WS_POPUP should take care of the problem;
DWORD wndExStyle = WS_EX_OVERLAPPEDWINDOW;
DWORD wndStyle = WS_POPUP | WS_SYSMENU;
g_hWnd = CreateWindowEx(wndExStyle, wcl.lpszClassName, L"junk",
wndStyle, 0, 0, 0, 0, 0, 0, wcl.hInstance, 0);
//Somewhere later
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
wglCreateContextAttribsARB(g_hDC, 0, attribList);
//Finally
ShowWindow(g_hWnd, SW_MAXIMIZE);
UpdateWindow(g_hWnd);
edit 1:
removed WS_BORDER
That border is caused by the use of WS_EX_OVERLAPPEDWINDOW. The fact that WS_EX_OVERLAPPEDWINDOW is defined as WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE makes it very clear what is going on.
Remove that extended style and the border goes away.
Including WS_BORDER in the style causes a thin border to be added to the window. Remove it from the style.
Related
I am new to ImGui, and trying to set the max and min window size. I am using the example dx10 ImGui code. I understand that this line will set the width and hight of the window at the start to be 600*800:
HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Micheal's Application", WS_OVERLAPPEDWINDOW, 100, 100, 600, 800, NULL, NULL, wc.hInstance, NULL);
How do I disable the user's ability to resize this window?
WS_OVERLAPPEDWINDOW is defined as
(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
where
WS_THICKFRAME 0x00040000L The window has a sizing border. Same as the WS_SIZEBOX style.
So, you need to clear WS_THICKFRAME bit in the window style:
WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME
I have a button and an EDIT window i named "textbox" initially. What i want to achieve is: when i press the button, the EDIT window's border will be remove and it's text is also changed. Here is how i initial them:
HWND textbox; //global variable
//in WM_CREATE:
CreateWindowEx(NULL, L"BUTTON", L"Remove border",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 10, 150, 40, hwnd,
(HMENU)IDC_TEXTBOX, NULL, NULL);
textbox = CreateWindowEx(
NULL, L"EDIT", NULL,
WS_CHILD | WS_BORDER | WS_VISIBLE | ES_MULTILINE,
100, 100, 200, 100, hwnd, (HMENU) 0, NULL, NULL
);
SetWindowText(textbox, L"the initial text");
Since there is WS_BORDER in its style at the start, i thought removing it from window style will remove the border so this is my first attempt:
//In WM_COMMAND
case IDC_TEXTBOX: //if button is pressed
lStyle = GetWindowLongPtr(textbox, GWL_STYLE);
lStyle &= ~(WS_CHILD | WS_VISIBLE | ES_MULTILINE);
SetWindowLongPtr(textbox, GWL_STYLE, lStyle);
SetWindowPos(textbox, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
SWP_NOZORDER | SWP_NOOWNERZORDER);
SetWindowText(textbox, L"how to remove the border around this text???");
break;
The code above didn't work. The window disappeared after i pressed the button. In the second attempt i followed the answer in this question:
case IDC_TEXTBOX:
lStyle = GetWindowLongPtr(textbox, GWL_STYLE);
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
SetWindowLongPtr(textbox, GWL_STYLE, lStyle);
lExStyle = GetWindowLongPtr(textbox, GWL_EXSTYLE);
lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
SetWindowLongPtr(textbox, GWL_EXSTYLE, lExStyle);
SetWindowPos(textbox, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
SWP_NOZORDER | SWP_NOOWNERZORDER);
SetWindowText(textbox, L"how to remove the border around this text???");
break;
This time, the text has changed but the border is still around after pressing the button:
so the question is: What did i do wrong in the 1st and 2nd attempt? And what should i do to remove the EDIT window border?
I would have made this a comment under your answer, but I don't have enough reputation.
Others in the comments have said that "Many of the system controls cache their initial styles and never update them" but strangely you can add a border after creation but just not remove it. So it seems that the border style is actually not cached.
My current solution is to recreate the control. Even though I can live with this solution (at the moment), I do not like it.
-Edit-
Never mind the above. I found that adding WS_BORDER after creation is actually a different border than the border added with WS_BORDER at creation. When you create the edit control with WS_BORDER and add WS_BORDER to it again with SetWindowLong() then the edit control now has 2 visible borders appearing as a single 2 pixel border. The WS_BORDER added after creation can be removed after creation but the initial WS_BORDER added at creation cannot be removed. So it appears that the initial edit border actually does get cached.
So, I'm using this for a game that starts as fullscreen.
I first do this to make it window mode:
SetWindowLongPtr(pantalla, GWL_STYLE, WS_CAPTION | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU);
SetWindowLongPtr(pantalla, GWL_EXSTYLE, WS_EX_WINDOWEDGE);
SetWindowPos(pantalla, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
After that I want to be able to hide the window, and to do so I'm using this:
SetWindowLongPtr(pantalla, GWL_EXSTYLE, WS_EX_NOACTIVATE);
SetWindowPos(pantalla, HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
That EX_NOACTIVATE was just a test, didn't work.
The problem is; the window hides perfectly, but then whenever I click (anywhere in the screen) the hidden program appears right back. How can I prevent that?
Suppose hCtl is a handle to a control created without the WS_VISIBLE flag such as:
HWND hCtl = CreateWindowEx(0, WC_STATIC, L"some text",
WS_CHILD | SS_NOTIFY, // no WS_VISIBLE flag
0, 0, 0, 0, hWndParent, (HMENU)IDC_STATIC1, g_hInst, 0);
Is there a more straightforward way to make it visible than the following?
void make_visible(HWND hCtl, HWND hWndParent) {
SetWindowLongPtr(hCtl, GWL_STYLE,
GetWindowLongPtr(hCtl, GWL_STYLE) | WS_VISIBLE);
RECT rc{};
GetClientRect(hCtl, &rc);
MapWindowRect(hCtl, hWndParent, &rc);
InvalidateRect(hWndParent, &rc, TRUE);
UpdateWindow(hWndParent);
//ShowWindow(hCtl, SW_SHOW); // no use: does not update window
//SetWindowPos(hCtl, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); // no use: does not update window
}
To make a child control visible, call SetWindowPos like this:
SetWindowPos(hCtl, 0, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
Your code to call MapWindowRect, InvalidateRect, UpdateRect etc. should be removed.
Perhaps the real problem you have is that you have created the static control with zero width and height.
The normal way to make a window visible is only the function ShowWindow. There is no need dealing with flags and so on. Usually you use SW_SHOW as a parameter for a child window. Check the other values and use what you think is appropriate.
If the window has a visible rectangle and isn't covered by another window it will show up. Even UpdateWindow calls are not needed. The window will show up in the next paint cycle. If your control has a size of 0,0,0,0 (as it was created) it will never show up.
There is also a ShowWindowAsync function for the use if the window is on a different thread to avoid blocking.
BTW: I don't understand what you try with invalidating the parent window area. If there is a child window clipping (WS_CLIPCHILDREN) it has no effect.
I believe your problem is that you're explicitly setting the WS_VISIBLE style yourself and then calling ShowWindow, which confuses Windows into believing that the window is already visible and doesn't need to be repainted.
Just call ShowWindow. There should be no need to explicitly set WS_VISIBLE yourself because ShowWindow already does it. You should not need to forcibly repaint your control.
Additionally, if you find some need to explicitly invalidate your control, it should be sufficient to just do InvalidateRect(hCtl, NULL) and not bother with GetClientRect and MapWindowRect.
Below is code, which I am using for creating child windows:
case WM_CREATE:
hInst = ((LPCREATESTRUCT) lParam) -> hInstance;
hWnd1 = CreateWindowEx( WS_EX_CLIENTEDGE | WS_EX_LEFT,
"edit", NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | ES_MULTILINE | WS_VSCROLL,
0, 0, 0, 0,
hWnd, (HMENU) 1,
hInst, NULL );
hWnd2 = CreateWindowEx( WS_EX_CLIENTEDGE | WS_EX_LEFT,
"edit", NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | ES_MULTILINE | WS_VSCROLL,
0, 0, 0, 0,
hWnd, (HMENU) 2,
hInst, NULL );
But this code produces horizontal splitter, and I want vertical splitter.
First I thought, if I change height and width parameters, I could create vertical splitter. But it was of no use.
For full code and sample example (in order to save space on SO):
http://old.sumitbirla.com/software/src/splitter.c
So, what is exactly keyword/parameter, which would produce vertical splitter bar.
The code you posted just creates two child windows. It has nothing to do with vertical or horizontal splitter. Handle the WM_SIZE message in the parent window to position and size the child windows for a vertical or horizontal split.