5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-10 22:19:46 +08:00

[windows] Fixes for window sizing

This commit is contained in:
Lea Anthony 2021-07-11 11:29:34 +10:00
parent 4f2788a294
commit 1748e8479f
4 changed files with 139 additions and 72 deletions

View File

@ -2,6 +2,7 @@
// License included in README.md
#include "ffenestri_windows.h"
#include "shellscalingapi.h"
#include "wv2ComHandler_windows.h"
#include <functional>
#include <atomic>
@ -42,6 +43,30 @@ char* LPWSTRToCstr(LPWSTR input) {
return output;
}
// Credit: https://building.enlyze.com/posts/writing-win32-apps-like-its-2020-part-3/
typedef int (__cdecl *PGetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE,UINT*,UINT*);
void getDPIForWindow(struct Application *app)
{
HMODULE hShcore = LoadLibraryW(L"shcore");
if (hShcore)
{
PGetDpiForMonitor pGetDpiForMonitor = reinterpret_cast<PGetDpiForMonitor>(GetProcAddress(hShcore, "GetDpiForMonitor"));
if (pGetDpiForMonitor)
{
HMONITOR hMonitor = MonitorFromWindow(app->window, MONITOR_DEFAULTTOPRIMARY);
pGetDpiForMonitor(hMonitor, (MONITOR_DPI_TYPE)0, &app->dpix, &app->dpiy);
}
} else {
// We couldn't get the window's DPI above, so get the DPI of the primary monitor
// using an API that is available in all Windows versions.
HDC hScreenDC = GetDC(0);
app->dpix = GetDeviceCaps(hScreenDC, LOGPIXELSX);
app->dpiy = GetDeviceCaps(hScreenDC, LOGPIXELSY);
ReleaseDC(0, hScreenDC);
}
}
struct Application *NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) {
// Create application
@ -88,6 +113,9 @@ struct Application *NewApplication(const char *title, int width, int height, int
// Used to remember the window location when going fullscreen
result->previousPlacement = { sizeof(result->previousPlacement) };
// DPI
result->dpix = result->dpiy = 0;
return result;
}
@ -179,30 +207,28 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
return 0;
}
// get pixel density
HDC hDC = GetDC(NULL);
double DPIScaleX = GetDeviceCaps(hDC, 88)/96.0;
double DPIScaleY = GetDeviceCaps(hDC, 90)/96.0;
ReleaseDC(NULL, hDC);
// update DPI
getDPIForWindow(app);
double DPIScaleX = app->dpix/96.0;
double DPIScaleY = app->dpiy/96.0;
RECT rcClient, rcWind;
RECT rcWind;
POINT ptDiff;
GetClientRect(hwnd, &rcClient);
GetWindowRect(hwnd, &rcWind);
int widthExtra = (rcWind.right - rcWind.left) - rcClient.right;
int heightExtra = (rcWind.bottom - rcWind.top) - rcClient.bottom;
int widthExtra = (rcWind.right - rcWind.left);
int heightExtra = (rcWind.bottom - rcWind.top);
LPMINMAXINFO mmi = (LPMINMAXINFO) lParam;
if (app->minWidth > 0 && app->minHeight > 0) {
mmi->ptMinTrackSize.x = app->minWidth * DPIScaleX + widthExtra;
mmi->ptMinTrackSize.y = app->minHeight * DPIScaleY + heightExtra;
mmi->ptMinTrackSize.x = app->minWidth * DPIScaleX;
mmi->ptMinTrackSize.y = app->minHeight * DPIScaleY;
}
if (app->maxWidth > 0 && app->maxHeight > 0) {
mmi->ptMaxSize.x = app->maxWidth * DPIScaleX + widthExtra;
mmi->ptMaxSize.y = app->maxHeight * DPIScaleY + heightExtra;
mmi->ptMaxTrackSize.x = app->maxWidth * DPIScaleX + widthExtra;
mmi->ptMaxTrackSize.y = app->maxHeight * DPIScaleY + heightExtra;
mmi->ptMaxSize.x = app->maxWidth * DPIScaleX;
mmi->ptMaxSize.y = app->maxHeight * DPIScaleY;
mmi->ptMaxTrackSize.x = app->maxWidth * DPIScaleX;
mmi->ptMaxTrackSize.y = app->maxHeight * DPIScaleY;
}
return 0;
}
@ -392,6 +418,7 @@ bool initWebView2(struct Application *app, int debugEnabled, messageCallback cb)
}
app->webviewController = controller;
app->webview = webview;
// Resize WebView to fit the bounds of the parent window
RECT bounds;
GetClientRect(app->window, &bounds);
@ -403,7 +430,64 @@ bool initWebView2(struct Application *app, int debugEnabled, messageCallback cb)
LPCWSTR html = (LPCWSTR) cstrToLPWSTR((char*)assets[0]);
app->webview->Navigate(html);
if( app->webviewIsTranparent ) {
wchar_t szBuff[64];
ICoreWebView2Controller2 *wc2;
wc2 = nullptr;
app->webviewController->QueryInterface(IID_ICoreWebView2Controller2, (void**)&wc2);
COREWEBVIEW2_COLOR wvColor;
wvColor.R = app->backgroundColour.R;
wvColor.G = app->backgroundColour.G;
wvColor.B = app->backgroundColour.B;
wvColor.A = app->backgroundColour.A == 0 ? 0 : 255;
if( app->windowBackgroundIsTranslucent ) {
wvColor.A = 0;
}
HRESULT result = wc2->put_DefaultBackgroundColor(wvColor);
if (!SUCCEEDED(result))
{
switch (result)
{
case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND):
{
MessageBox(
app->window,
L"Couldn't find Edge installation. "
"Do you have a version installed that's compatible with this "
"WebView2 SDK version?",
nullptr, MB_OK);
}
break;
case HRESULT_FROM_WIN32(ERROR_FILE_EXISTS):
{
MessageBox(
app->window, L"User data folder cannot be created because a file with the same name already exists.", nullptr, MB_OK);
}
break;
case E_ACCESSDENIED:
{
MessageBox(
app->window, L"Unable to create user data folder, Access Denied.", nullptr, MB_OK);
}
break;
case E_FAIL:
{
MessageBox(
app->window, L"Edge runtime unable to start", nullptr, MB_OK);
}
break;
default:
{
MessageBox(app->window, L"Failed to create WebView2 environment", nullptr, MB_OK);
}
}
}
}
messageFromWindowCallback("Ej{\"name\":\"wails:launched\",\"data\":[]}");
return true;
}
@ -500,61 +584,6 @@ void Run(struct Application* app, int argc, char **argv) {
// Add webview2
initWebView2(app, debug, initialCallback);
if( app->webviewIsTranparent ) {
wchar_t szBuff[64];
ICoreWebView2Controller2 *wc2;
wc2 = nullptr;
app->webviewController->QueryInterface(IID_ICoreWebView2Controller2, (void**)&wc2);
COREWEBVIEW2_COLOR wvColor;
wvColor.R = app->backgroundColour.R;
wvColor.G = app->backgroundColour.G;
wvColor.B = app->backgroundColour.B;
wvColor.A = app->backgroundColour.A == 0 ? 0 : 255;
if( app->windowBackgroundIsTranslucent ) {
wvColor.A = 0;
}
HRESULT result = wc2->put_DefaultBackgroundColor(wvColor);
if (!SUCCEEDED(result))
{
switch (result)
{
case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND):
{
MessageBox(
app->window,
L"Couldn't find Edge installation. "
"Do you have a version installed that's compatible with this "
"WebView2 SDK version?",
nullptr, MB_OK);
}
break;
case HRESULT_FROM_WIN32(ERROR_FILE_EXISTS):
{
MessageBox(
app->window, L"User data folder cannot be created because a file with the same name already exists.", nullptr, MB_OK);
}
break;
case E_ACCESSDENIED:
{
MessageBox(
app->window, L"Unable to create user data folder, Access Denied.", nullptr, MB_OK);
}
break;
case E_FAIL:
{
MessageBox(
app->window, L"Edge runtime unable to start", nullptr, MB_OK);
}
break;
default:
{
MessageBox(app->window, L"Failed to create WebView2 environment", nullptr, MB_OK);
}
}
}
}
// Main event loop
MSG msg;

View File

@ -14,6 +14,7 @@ extern void DisableWindowIcon(struct Application* app);
*/
import "C"
import (
"github.com/ztrue/tracerr"
"os"
"github.com/wailsapp/wails/v2/pkg/menu"
@ -105,6 +106,7 @@ been sent.
func checkFatal(err error) {
if err != nil {
tracerr.PrintSourceColor(err)
globalRadioGroupCache.Dump()
globalRadioGroupMap.Dump()
os.Exit(1)
@ -118,15 +120,17 @@ func createApplicationMenu(hwnd uintptr) {
return
}
var err error
window := win32Window(hwnd)
if globalApplicationMenu != nil {
checkFatal(globalApplicationMenu.Destroy())
}
var err error
globalApplicationMenu, err = createMenu(applicationMenu, appMenuType)
checkFatal(err)
err = setWindowMenu(win32Window(hwnd), globalApplicationMenu.menu)
err = setWindowMenu(window, globalApplicationMenu.menu)
checkFatal(err)
}

View File

@ -55,6 +55,10 @@ struct Application{
// placeholders
char* bindings;
char* initialCode;
// DPI
UINT dpix;
UINT dpiy;
};
#define ON_MAIN_THREAD(code) dispatch( [=]{ code; } )

View File

@ -39,6 +39,16 @@ const MF_UNCHECKED uint32 = 0x00000000
const MF_BYCOMMAND uint32 = 0x00000000
const MF_BYPOSITION uint32 = 0x00000400
const WM_SIZE = 5
const WM_GETMINMAXINFO = 36
type Win32Rect struct {
Left int32
Top int32
Right int32
Bottom int32
}
// ------------------- win32 calls -----------------------
func createWin32Menu() (win32Menu, error) {
@ -97,3 +107,23 @@ func selectRadioItem(selectedMenuID, startMenuItemID, endMenuItemID win32MenuIte
}
return nil
}
//
//func getWindowRect(window win32Window) (*Win32Rect, error) {
// var windowRect Win32Rect
// res, _, err := win32GetWindowRect.Call(uintptr(window), uintptr(unsafe.Pointer(&windowRect)))
// if res == 0 {
// return nil, err
// }
// return &windowRect, nil
//}
//
//func getClientRect(window win32Window) (*Win32Rect, error) {
// var clientRect Win32Rect
// res, _, err := win32GetClientRect.Call(uintptr(window), uintptr(unsafe.Pointer(&clientRect)))
// if res == 0 {
// return nil, err
// }
// return &clientRect, nil
//}
//