標籤:
單獨改變座標的代碼如下,可不斷左移:
procedure TForm1.Button1Click(Sender: TObject);begin SetWindowPos(panel1.Handle, 0, panel1.Left-10, panel1.Top, panel1.Width, panel1.Height, SWP_NOZORDER + SWP_NOACTIVATE);end;
照理每次改變座標,都會調用SetBounds,都會調用SetWindowPos函數,可是一旦我屏蔽UpdateBounds函數,控制項從第二次開始,就沒有效果了:
procedure TForm1.Button1Click(Sender: TObject);begin panel1.Left:=panel1.Left-10;end;
這是為什麼呢?原因是,在使用API達到相應的目的之後,必須修改Delphi的屬性值,以備下次使用。否則Delphi下次還是按照原來的left值再減去10,這樣看上去就沒有被移動。所以關鍵是UpdateBounds裡的代碼:
procedure TWinControl.UpdateBounds;var ParentHandle: HWnd; Rect: TRect; WindowPlacement: TWindowPlacement;begin GetWindowRect(FHandle, Rect); // API,取得客戶區,注意第二個參數是指標,但Delphi裡直接使用 // important 如果具有子視窗風格,就要根據父控制項在螢幕上的位置重新顯示 if GetWindowLong(FHandle, GWL_STYLE) and WS_CHILD <> 0 then begin ParentHandle := GetWindowLong(FHandle, GWL_HWNDPARENT); // API,fixme 還可以這樣簡單取得父控制項控制代碼?就這一處 if ParentHandle <> 0 then begin Windows.ScreenToClient(ParentHandle, Rect.TopLeft); // API Windows.ScreenToClient(ParentHandle, Rect.BottomRight); end; end; // important 使用API取得實際效果後,也要改變Delphi的屬性值,否則屬性值還是保持上一次的值,這樣下一次看起來就無法移動了 // 錯誤:顯示完以後,根據windows內部資訊更新Win控制項的屬性 // important 如果這裡exit,那麼只有第一次的時候座標可以移動,後面都無法移動了。說到底都是通過這裡起作用的 FLeft := Rect.Left; FTop := Rect.Top; FWidth := Rect.Right - Rect.Left; FHeight := Rect.Bottom - Rect.Top; // 更新座標和長寬後,要重新鉚接 // fixme 難道不用對齊嗎,別處好多地方也都是這樣 UpdateAnchorRules;end;
的最後幾句。這樣就達到了修改值的目的。
--------------------------------------------------------------------
另一種辦法改變Windows視窗的座標(親測):
procedure TForm1.Button2Click(Sender: TObject);var WindowPlacement: TWindowPlacement; // Windows結構類型,包含最大化已最小化的視窗位置等6項內容begin WindowPlacement.Length := SizeOf(WindowPlacement); GetWindowPlacement(Panel1.Handle, @WindowPlacement); // API,取得結構體指標,包括7項內容 // 更改視窗的位置資訊 WindowPlacement.rcNormalPosition := Panel1.BoundsRect; WindowPlacement.rcNormalPosition.Left := WindowPlacement.rcNormalPosition.Left - 10; WindowPlacement.rcNormalPosition.Right := WindowPlacement.rcNormalPosition.Right - 10; SetWindowPlacement(Panel1.Handle, @WindowPlacement);end;
使用SetWindowPos API函數移動視窗後,還需修改Delphi的屬性值,以備下次使用,否則就會出問題(不是API不起作用,而是使用了錯誤的座標值)