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:
parent
4f2788a294
commit
1748e8479f
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,10 @@ struct Application{
|
||||
// placeholders
|
||||
char* bindings;
|
||||
char* initialCode;
|
||||
|
||||
// DPI
|
||||
UINT dpix;
|
||||
UINT dpiy;
|
||||
};
|
||||
|
||||
#define ON_MAIN_THREAD(code) dispatch( [=]{ code; } )
|
||||
|
@ -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
|
||||
//}
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user