我需要从Delphi程序中获取桌面分辨率 但是,如果该程序不是DPI意识到Windows会对真正的屏幕分辨率撒谎,那么所有类型的问题都会从这里出现。
由于让程序完全了解DPI(我尝试避免WMI solution)是太多的工作了,我正在考虑使用一个快速的肮脏技巧:我将创建一个微观的DPI感知控制台程序,阅读真正的分辨率。
主程序将在每次需要分辨率时使用启动这个小程序(隐藏)。看起来很简单。正确?
问题1:我还有其他(更好)的选择吗? 问题2:我试图创建那个小程序。虽然有10行代码,但其EXE大小为2.1MB,内存占用为5.4MB! 我能把它缩小吗?如果程序足够小(RAM低于1MB),我可以让它一直运行而不会惹恼用户。
答案 0 :(得分:2)
问题1:我还有其他(更好)的选择吗?
您可以根据之前的问题使用WMI:How to obtain the real screen resolution in a High DPI system?
问题2:我试图创建那个小程序。虽然有10行代码,但其EXE大小为2.1MB,内存占用为5.4MB!我能把它缩小吗?
诀窍是避免使用任何VCL单元,并尽量减少您使用的RTL单元的数量。您的目标应该是仅使用Windows
单位。或者甚至避免它,并为您需要的功能创建自己的Windows API导入。
另一种选择是使用不同的编程语言创建此程序,该语言能够更好地删除死代码。我可能会用一个简短的C程序来做这件事。
答案 1 :(得分:0)
这是30KB的普通图标,15KB(如果你使用UPX),用Delphi 10 Seattle编译,在我的系统中大约需要150-200ms。
program ScreenSupport;
{$APPTYPE CONSOLE}
{$WEAKLINKRTTI ON}
{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
uses
Windows,
Messages;
{$R *.res}
{$SetPEFlags $0200} // IMAGE_FILE_DEBUG_STRIPPED} // $0200
{$SetPEFlags $0004} // IMAGE_FILE_LINE_NUMS_STRIPPED} // $0004
{$SetPEFlags $0008} // IMAGE_FILE_LOCAL_SYMS_STRIPPED} // $0008
{$SetPEFlags $0001} // IMAGE_FILE_RELOCS_STRIPPED} // $0001
Const WM_APP = $8000;
msgSendScreenres = WM_APP+1;
SM_CXVIRTUALSCREEN = 78;
SM_CYVIRTUALSCREEN = 79;
function GetDesktopHeight: Integer;
begin
Result := GetSystemMetrics(SM_CYVIRTUALSCREEN);
end;
function GetDesktopWidth: Integer;
begin
Result := GetSystemMetrics(SM_CXVIRTUALSCREEN);
end;
procedure SendScreenRes(t: THandle);
begin
if t = 0 then Exit;
PostMessage(t,msgSendScreenres,GetDesktopWidth,GetDesktopHeight);
end;
function IsAnyParam(s: string): Boolean;
Var a: Integer;
begin
Result := False;
if ParamCount = 0 then Exit;
for a := 1 to ParamCount do
if ParamStr(a) = s then Exit(True);
end;
function StrToInt(const S: string): Integer;
Var E: Integer;
begin
Val(S, Result, E);
end;
begin
// screen res requested
if IsAnyParam('-screenres') then begin
try
SendScreenRes(StrToInt(ParamStr(2)));
except
Exit;
end;
end;
end.
要使用它,请从主应用程序中调用它:
Const msgSendScreenres = WM_APP+1;
ShellExecute(0,'open','ScreenSupport.exe',PChar('-screenres '+IntToStr(Form1.Handle)),'',SW_HIDE);
然后在主机上的私人声明中添加它
procedure WMScreenRes(var Msg: TMessage); message msgSendScreenres;
然后抓住它
procedure TForm1.WMScreenRes(var Msg: TMessage);
begin
ScreenWidth := Msg.WParam;
ScreenHeight := Msg.LParam;
end;