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

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.

Related

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.

How to make Window full screen in VisualStudio SkeletonBasics-D2D 2013

I'm currently using the SkeletonBasics-D2D library. I would like to give a presentation with the skeleton but need make the window fullscreen. Here are the notes I currently worked through and my next step is potentially modifying the .rc file to work with the full screen windowed app; however, I'd like to ask first is anyone knows another way.
Potentially it could just be manipulating this code in my SkeletonBasics.rc file :
IDD_APP DIALOGEX 0, 0, 512, 424
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_CONTROLPARENT | WS_EX_APPWINDOW
CAPTION "Skeleton Basics"
CLASS "SkeletonBasicsAppDlgWndClass"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_VIDEOVIEW,"Static",SS_BLACKFRAME,0,0,512,384
LTEXT "Click 'Seated' to change skeletal pipeline type!",IDC_STATUS,0,413,511,11,SS_SUNKEN,WS_EX_CLIENTEDGE
CONTROL "Seated",IDC_CHECK_SEATED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,238,391,55,8
END
Notes from code :
creating a window causes different signals to be generated than a dialog
where a dialog expects WM_INITDIALOG on create, a window should expect WM_NCCREATE
the dialog's DLGPROC was being set with CreateDialogParamW(). The window's WNDPROC is set within a WNDCLASS structure and then registered before CreateWindow()
the window's class name is important, as it's referred to in the SkeletonBasics.rc file wc.lpszClassName = L"SkeletonBasicsAppDlgWndClass";
need to determine all messages sent to the window and handle them appropriately
This tutorial is a great example of full screen and have used it to convert my application into full screen.
To get there, I needed to change the dialog proc to a window.
http://www.directxtutorial.com/Lesson.aspx?lessonid=11-4-4

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

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.

WINAPI Button background

In WINAPI, I create a button like:
case WM_CREATE:
{
Start = CreateWindowEx(WS_EX_TRANSPARENT, "Button", "Start", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 20, 50, 75, 25, window, (HMENU)ID_START, hInstance, NULL);
break;
}
The button looks like:
But I need it to look like this one (which I did in .Net):
How can I get rid of that black border/background?
Start = CreateWindowEx(WS_EX_TRANSPARENT, ...);
You got the black outline because you used the WS_EX_TRANSPARENT style flag. It isn't clear why you used it, there's not much you can do with it when you use the Button control. It is otherwise probably the least understood style flag. Pass 0 instead to get a normal looking button.
It is otherwise a lost cause to get the exact look of a .NET button, Winforms doesn't use the built-in Button control. It creates its own, using a custom renderer to get the gradient look. Reproducing that native code is a lot of work.
I think the border you are seeing is because the button has the "Default Button" property. If you turn that off, then it will have a normal border. The Default property just tells Win32 which button to activate if the users hits ENTER on the dialog/form. If you only have one button, then it will always have the default property. If you add a second, it will not.
The property is the BS_DEFPUSHBUTTON property, so in your CreateWindowEx call, you should be able to do something like:
Start = CreateWindowEx(WS_EX_TRANSPARENT, "Button", "Start", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | ~BS_DEFPUSHBUTTON, 20, 50, 75, 25, window, (HMENU)ID_START, hInstance, NULL);
If not, you'll have to set it with ModifyStyle or ModifyStyleEx, and pass it in the "Remove" parameter. I forget which one the specific styles have to be passed in, but if I recall correctly, it's the normal style params, NOT the EX params.
I haven't tested this, but try creating the button like this:
Start = CreateWindowEx(0, WC_BUTTON, "Start", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT, 20, 50, 75, 25, window, (HMENU)ID_START, hInstance, NULL);
break;
It also might depend on how you've created your main window. Can you post the code for your main window creation?
EDIT: I mis-identified the border as the default-button border. As David Hefferman pointed out, it's not. That is, I have now reproduced that border effect; when the program starts there is no border, but just a little mousing over the left button creates the border – at least in Windows 7.
Original answer follows:
The black border is because it's default. You shouldn't interfere with the system's visualization of default buttons etc. Users rely on those cues.
To change the font, maybe, like, WM_SETFONT?
Disclaimer: I haven't tried that. It might be you need to handle WM_CTRLCOLOR or something like that. Just try it out, and in the end, if the default buttons don't cut it for you, simply implement your own button.

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.