DWM

在windows平台上开发桌面程序必然会遇到窗口相关的问题, 比如使用Qt创建一个无边框窗口会发现原生窗口的缩放特效、阴影和窗口管理功能失效了, 如何解决相关问题呢,这就需要了解DWM(Desktop Window Manager).

windows自从Windows Vista后,引入了DWM Desktop composition. DWM可以实现玻璃窗框、3D 窗口过渡动画、Windows Flip 、Windows Flip3D 、高分辨率支持以及各种功能.

// 使能DWM
HWND wnd = (HWND)this->GetMainWindow()->winId();
// enable borderless and keep aero effects.
SetWindowLongPtr(wnd, GWL_STYLE, WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPCHILDREN);
// enable shadow
const MARGINS shadow_on = { 1, 1, 1, 1 };
DwmExtendFrameIntoClientArea(wnd, &shadow_on);
//redraw frame
SetWindowPos(wnd, Q_NULLPTR, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
ShowWindow(wnd, SW_SHOW);

结合DMW创建的无边框窗口在用户体验上相对完美,既可以优化windows原生标题栏的样式、又兼容窗口管理和缩放等动效.

WMI

在windows平台上开发桌面程序会遇到一些和硬件设备相关的需求, 常规有两种方案;

  1. 通过api访问设备
  2. 通过WMI工具访问

WMI(Windows Management Instrumentation)是windows应对企业信息管理开发的一项协议标准.用于系统、程序、网络、设置和其他托管设备的管理. 其中通过WMIC命令行工具即可以进行硬件资源的访问. 比如:

访问GPU

QProcess gpuProcessGetName;
gpuProcessGetName.start("wmic path win32_VideoController get Name,DriverDate,DriverVersion ");
gpuProcessGetName.waitForFinished();
QString gpuNameResult = gpuProcessGetName.readAllStandardOutput();

访问CPU

QProcess cpuProcess;
cpuProcess.start("wmic cpu get Name");
cpuProcess.waitForFinished();
QString cpuResult = cpuProcess.readAllStandardOutput();

International Support

使用跨平台框架开发Windows桌面程序会遇到一些编码问题, 因为历史原因大陆地区windows默认是GBK编码不是utf8编码. 所以部分用户会遇到切换时区、编码后软件乱码的问题.所以需要确保软件的字符集和编码符合windows Internationalization标准

#add Unicode Character Set
add_definitions(-DUNICODE -D_UNICODE)
#add utf8 encoding
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/source-charset:utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/execution-charset:utf-8>")

Dll load

windows平台下的动态库加载, 相关接口在libloaderapi.h头文件中

LoadLibrary加载.dll动态库后, GetProcAddress绑定函数指针即可.

HINSTANCE hDLL = LoadLibrary("yourDLL.dll");

FunctionNameType func = (FunctionNameType)GetProcAddress(hDLL, "FunctionName"); 

func();  // 调用 DLL

FreeLibrary(hDLL); // 释放 DLL

IPC

windows平台下的IPC, 相关接口主要在processthreadsapi.h头文件中

常见的接口:

  • GetCurrentProcessId
  • OpenProcess
  • GetThreadId
  • OpenThread
    等等