【发布时间】:2016-10-25 10:26:48
【问题描述】:
目前的目标是在拖动窗口时使窗口变小(卷起),而不是使其变为原始大小。
我试图在 WM_MOVING 调用中更改窗口大小,但它只是像地狱一样闪烁(将大小更改为小,然后在下一帧 - 将大小更改为原始大小,每 2 帧重复一次)。
如果我设置了一个标志,没有任何反应,窗口的原始大小保持不变。
WM_MOVING:
begin
if(Moving) = false then
begin
GetWindowRect(Window, move_rect);
SetWindowPos(Window, 0, 0, 0, move_rect.Width, 0, SWP_NOMOVE or SWP_NOZORDER);
Moving := true;
end;
end;
更新 2:这里有完整的应用程序代码,有很多未使用的变量并且没有错误处理:
unit Unit1;
interface
uses
System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
Vcl.Dialogs, Vcl.StdCtrls, System.JSON, winapi.Windows, winapi.Messages, SysUtils;
type
TForm1 = class(TForm)
Button2: TButton;
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
test_window : TWndClassEx;
Window, parentHWND : HWND;
mmsg: msg;
Button, Label1 : hwnd;
moving_flag : bool;
move_x, move_y : integer;
move_rect : TRect;
window_rolled : bool;
implementation
{$R *.dfm}
function WindowProc(wnd: hwnd; msg: integer; wparam: wparam; lparam: lparam):lresult;stdcall;
var
hRegX: HRGN;
WindowRect: TRect;
int_x, int_y : integer;
p_rect : Prect;
begin
case msg of
WM_DESTROY:
begin
PostQuitMessage(0);
Button := 0;
label1 := 0;
result := 0;
Window := 0;
exit;
end;
WM_COMMAND:
begin
case LoWord( wParam ) of
1: MessageBox(Window,'Button','Title',0);
end;
end;
WM_MOVING:
begin
if(moving_flag) = false then
begin
GetWindowRect(Window, move_rect);
SetWindowPos(Window, 0, 0, 0, move_rect.Width, 0, SWP_NOMOVE or SWP_NOZORDER);
moving_flag := true;
end;
end;
//WM_MOUSEMOVE:
//WM_LBUTTONDOWN:
WM_EXITSIZEMOVE:
begin
end;
else
result := DefWindowProc(wnd,msg,wparam,lparam);
end;
end;
procedure CreateWinApiForm;
begin
if Window = 0 then
begin
test_window.cbSize := sizeof(test_window);
test_window.style := 0;
test_window.lpfnWndProc := @windowproc;
test_window.hInstance := hInstance;
test_window.hIcon := LoadIcon(hInstance,'MAINICON');
test_window.hCursor := LoadCursor(0,IDC_ARROW);
test_window.hbrBackground := COLOR_BTNFACE+1;
test_window.lpszClassName := 'MyWindow';
if winapi.windows.registerclassEx(test_window) = 0 then
MessageBox(0, 'Error registering window', 'Title', MB_OK);
Window := CreateWindowEx(0, test_window.lpszClassName, 'Random text', WS_CAPTION or WS_MINIMIZEBOX or WS_SYSMENU, 300, 300, 350, 130, 0, 0, hInstance, nil);
GetWindowRect(Window, move_rect);
label1:=CreateWindow('static','Label?',WS_VISIBLE or WS_CHILD or BS_TEXT,6,25,330,40, Window,2,hInstance,nil);
Button:=CreateWindow('button','Button',WS_VISIBLE or WS_CHILD,6,73,110,25, Window,1,hInstance,nil);
ShowWindow(Window, SW_Show);
end
else
MessageBox(0, 'Window already exists', 'title', MB_OK);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
CreateWinApiForm;
while getmessage(mmsg,0,0,0) do
begin
translatemessage(mmsg);
dispatchmessage(mmsg);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Window := 0;
move_x := 0;
move_y := 0;
moving_flag := false;
window_rolled := false;
end;
end.
更新 3:另外,我看到有人使用 SetWindowRgn 发布了答案,但由于某种原因,在我调用这个之后,窗口转换为“经典”视图,没有阴影等。
【问题讨论】:
-
if(Moving) = false then->if not Moving then是一个非常基本的 Pascal 习语。如果要更改表单的大小,请使用 VCL 函数来执行此操作。大概。为什么我们不能有minimal reproducible example。我们是否应该单独花时间建造一个?如果您提供了一份,我们将更容易提供帮助。你的用户当然会讨厌你这样做。移动时把窗口变小?那看起来会很糟糕。最好确保您的卸载程序经过良好测试。 -
如果您使用自定义
drag image而不是在移动时尝试更改窗口大小,您可能会获得更好的结果。参见例如blong.com/Conferences/BorCon2001/DragAndDrop/…。或者只是谷歌“delphi自定义拖动图像”。 -
@MartynA 的目标是在纯 WinApi 中制作应用程序,无需任何 VCL 等。
-
我猜你需要一点时间来制作minimal reproducible example。完成此操作并更新问题后,我们可以查看它。
-
好吧,这段代码让它像地狱一样闪烁。