`SetWindowLong()` function doesn't change window style even after calling `SetWindowPos()` - c++

I create the static control with the code below:
hWnd = CreateWindowExW( 0,
L"STATIC",
Content.c_str(),
SS_LEFT | WS_VISIBLE | WS_CHILD /*| SS_SUNKEN*/,
200,
120,
120,
40,
hWndParent,
NULL,
hInstance,
NULL);
If I enable the SS_SUNKEN style in the creation code above, the created static control appears sunken successfully.
But, what I'm trying to do is the change the control style after its creation.
I tried this:
void BaseWindowClass::AddStyle(DWORD NewStyle)
{
// NewStyle = 0x00001000 = SS_SUNKEN
LONG oldstyle, changedstyle;
oldstyle=SetWindowLongW(hWnd, GWL_STYLE, changedstyle=GetWindowLongW(hWnd, GWL_STYLE) | NewStyle);
UpdateWindowStyles();
// oldstyle = 0x50000000
// changedstyle = 0x50001000 (everything looks normal)
}
void BaseWindowClass::UpdateWindowStyles()
{
BOOL success;
success=SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
// success = 0x00000001 (non-zero: SetWindowPos sucseeded)
}
Documentation:
SetWindowLong()
SetWindowPos()
I call SetWindowPos() after calling SetWindowLongW() because in the documentation of SetWindowLong, it says:
Certain window data is cached, so changes you make using SetWindowLong will not take effect until you call the SetWindowPos function. Specifically, if you change any of the frame styles, you must call SetWindowPos with the SWP_FRAMECHANGED flag for the cache to be updated properly.
And, in the documentation of SetWindowPos, it says:
If you have changed certain window data using SetWindowLong, you must call SetWindowPos for the changes to take effect. Use the following combination for uFlags: SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED.
Even after changing SetWindowLongW() and SetWindowPos() the style of my static control does not change.
What am I doing wrong, or what am I missing?

SS_SUNKEN effectively sets WS_EX_STATICEDGE in the extended styles (GWL_EXSTYLE) window long, so you can update GWL_EXSTYLE appropriately and reposition as you're currently doing.

Even though SS_SUNKEN does affect the frame of a static control, it isn't one of the "frame styles" that note is referring to.
That note refers to generic frame styles that affect all windows like WS_BORDER or WS_EX_CLIENTEDGE - styles that require a recalculation of a window's non-client area when changed.
Many of the system controls cache their styles upon creation and don't update the cache even if you change the styles via SetWindowLong. I would guess that's what's happening here - if you don't create the static control with SS_SUNKEN, you can't add it later. Your best option would be to simply destroy and recreate the control with the new style.

Related

How do I enable zooming in the Win32 Rich Edit control?

I'm having trouble getting my Rich Edit control to accept the zoom ratio I specify when sending it the EM_SETZOOM message. I create the control using the following line of code:
editWrap = CreateWindowEx(0, MSFTEDIT_CLASS, nullptr, ES_EX_ZOOMABLE | ES_MULTILINE |
WS_VISIBLE | WS_CHILD | WS_VSCROLL | ES_AUTOVSCROLL | ES_DISABLENOSCROLL, 0, 0, 0, 0,
hwnd, nullptr, appInstance, nullptr);
Whenever I try to send it the EM_SETZOOM message the return value is always FALSE no matter what I specify as the WPARAM and LPARAM. I also tried putting ES_EX_ZOOMABLE as the first parameter of the CreateWindowEx call with the same results.
Zooming with the mouse works as expected. That's not the issue here. I'm trying to set the zoom programmatically.
I'm using the following code to send the message:
SendMessage(getCurrentEditor(), EM_SETZOOM, MAKEWPARAM(64, 0), MAKELPARAM(1, 0));
You are passing in the ES_EX_ZOOMABLE in the wrong parameter of CreateWindowEx(). You are passing it in the dwStyle parameter, but it is an extended window style so it needs to be passed in the dwExStyle parameter instead, eg:
editWrap = CreateWindowEx(ES_EX_ZOOMABLE, MSFTEDIT_CLASS, nullptr, ES_MULTILINE |
WS_VISIBLE | WS_CHILD | WS_VSCROLL | ES_AUTOVSCROLL | ES_DISABLENOSCROLL, 0, 0, 0, 0,
hwnd, nullptr, appInstance, nullptr);
Note that the EM_SETZOOM message is only supported on Windows Vista and later, in RichEdit 3.0 and later (you are using 4.1). You didn't indicate which Windows version you are using, or what your ratio values are set to. So it is hard to diagnose why exactly EM_SETZOOM returns FALSE. All that means is that the ratio wasn't accepted, but not WHY it wasn't accepted. Are you able to zoom the RichEdit with the mouse using Ctrl+MouseWheel? That will tell you whether ES_EX_ZOOMABLE is taking effect or not.
On a separate note: you are creating your RichEdit with a width and height of 0! Are you sure that is what you really want?
It turns out that the control won't accept a zoom factor of 64/1. I found that out by reading the Windows Forms documentation on the RichTextBox control. The Win32 API documentation just said the zoom factor had to be a number between 1/64 and 64. The Windows Forms documentation says it has to be "between 1/64 and 64.0, not inclusive". When I changed my test code to send 63/1 to the control, it worked as expected.

Draw Resource Icon on Button

I would like to draw my program's icon on an "owner-drawn" button. This could be either an icon in the resource file, or the generic Windows icon. But, even after endless searching, I have not been able to find the code for this. I have come across bits and pieces of answers. But, no complete explanations.
Sorry that I have no code to post. I am totally lost on this one. Either standard Win API or GDI+ will work for me.
When you create the button, add BS_ICON style, then get the handle to your icon, you can use LoadImage.
Finally send BM_SETIMAGE message with the handle to your icon.
Here is the code sample:
HWND button1 = CreateWindow(TEXT("Button"), TEXT("OK"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_ICON,
50, 50, 50, 50, hwnd, (HMENU)1001, hInstance, NULL);
HICON hIcon = (HICON)LoadImage( // returns a HANDLE so we have to cast to HICON
NULL, // hInstance must be NULL when loading from a file
L"iconname.ico", // the icon file name
IMAGE_ICON, // specifies that the file is an icon
0, // width of the image (we'll specify default later on)
0, // height of the image
LR_LOADFROMFILE | // we want to load a file (as opposed to a resource)
LR_DEFAULTSIZE | // default metrics based on the type (IMAGE_ICON, 32x32)
LR_SHARED // let the system release the handle when it's no longer used
);
SendMessage(button1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);

Win32 semi transparent window

I'm trying to get a semi transparent window with the Win32 API and C++. Despite the fact, that there
are around a million results trying to answer that question, none of those seem to have worked for my case.
I have a native Win32 window with a hosted WPF content inside it. Because I'm trying to create a custom
window frame (and that also works by now), I want the top part of the self drawn frame to be semi
transparent, possibly also applying the acrylic blur.
Looking at WPF, I could archive my goal using AllowTransparency = True on the window and with a
transparent background. Now I need a way to replicate that behavior with the Win32 API.
Technically, I can make the entire main window transparent (because the main window is the frame entirely
and the WPF hosted content is the client area), but even that didn't work (no transparency).
For reference, here is how I'm creating my window:
WNDCLASSEXW window_class_ex = {
sizeof(WNDCLASSEXW),
CS_HREDRAW | CS_VREDRAW,
window_callback,
0,
0,
application_instance,
nullptr,
LoadCursorW(nullptr, IDC_ARROW),
CreateSolidBrush(RGB(0, 0, 0)),
nullptr,
window_class,
nullptr
};
const HWND window_handle = CreateWindowExW(
0,
window_class,
L"WinSoup",
WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_EX_LAYERED,
CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
nullptr,
nullptr,
application_instance,
reinterpret_cast<LPVOID>(owner)
);
I have seen that I should use WS_EX_LAYERED, but also that didn't have the desired effect.
Of course the WPF content itself should not be transparent!
Ok, so, despite all the answers telling me to read the documentation and look at other
examples... turns out, I misplaced the WS_EX_LAYERED.
const HWND window_handle = CreateWindowExW(
WS_EX_LAYERED, // Needs to be placed here (extended style)
window_class,
L"WinSoup",
WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX, // Not here!
CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
nullptr,
nullptr,
application_instance,
reinterpret_cast<LPVOID>(owner)
);
Your question says
The WPF content itself should not be transparent!
You can use Set/UpdateLayeredWindowAttributes, but the opacity for your WPF content will change too.
If you really want to create a high-performance transparent/semi-transparent window, you need to specify the WS_EX_NOREDIRECTIONBITMAP flag instead of WS_EX_LAYERED. Then use DirectComposition with another graphics API to render your content.
Look at https://msdn.microsoft.com/magazine/dn745861.aspx for more details.

SetWindowPos not moving or resizing window

When I call SWP to try and move a resize a specific window. It does not move or resize.
SetWindowPos(hWndWindow, NULL, 0, 0, 500, 500, SWP_NOZORDER);
The window handle is valid. I tried both getting the handle with FindWindow and by manually setting the handle value to the window I wanted to resize.
When I use GetWindowPlacement, it says the window is SW_NORMAL and not SW_MAXIMIZE.
The window style is
0x160b0000 (WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU | WS_MINMIZEBOX | WS_MAXIMIZEBOX)
and the extend style is 0x0.
I have also tried setting the window to SW_NORMAL with ShowWindow before calling SetWindowPos.
SetWindowPos and MoveWindow both return non false values saying that they didn't fail.
Why is SetWindowPos and MoveWindow unable to move or resize this window?

List Control SetFocus Redraw Error on a Tab Control

Environment: Visual Studio 2008, Visual Studio Feature Pack, MFC Dialog App, Windows XP, New Common Controls.
I'm having a problem with a list control that happens to be on a tab control.
To reproduce the problem simply create a dialog based app. Place a tab control on that dialog, then put a list control onto that tab control. You don't need to add any code to the project. Just build and run. Set the focus to the list view and then either minimize the dialog or bring another window in front of it.
Now bring the dialog back to the foreground, the list will not draw itself correctly.
One thing I have tried is handle the set focus event for the list control, but left it with an empty method body, ie...
void CMyListControl::OnSetFocus(CWnd* window)
{
// Default();
}
Then the redraw problem goes away, however now you can not select items within the list. Uncommenting the call to Default makes the problem come back.
If I move the list off of the tab the problem goes away. If I set the focus to another control on the tab or dialog, the problem goes away. This is a weird one.
In fact, if you watch closely you can see the list drawing itself and then being obscured by the tab control.
I know it's late but I had them same problem today. You need to set ListView's parent to Tab control.
hWndTab = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TABCONTROL, NULL,
WS_CHILD | WS_TABSTOP | WS_VISIBLE,
0, 0, 0, 0, hWnd, (HMENU) IDC_TAB, hInstance, NULL);
hWndList = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, NULL,
WS_CHILD | WS_TABSTOP | WS_VISIBLE | LVS_REPORT,
0, 0, 0, 0, hWndTab, (HMENU) IDC_LIST, hInstance, NULL);
Note parent window handler for hWndList: hWndTab. Or you can use SetParent.