首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

如何避免多控制項表單重新佈局時閃爍(二):P/Invoke SendMessage 實作 BeginUpdate/EndUpdate 與任務列重繪修正

     編輯:關於C語言

核心思路:自訂 BeginUpdate/EndUpdate

非所有控制項皆提供 BeginUpdate/EndUpdate,需自行透過 Windows API 實作:

  1. SendMessage:使用 P/Invoke Interop Assistant 工具生成簽章。
  2. WM_SETREDRAW (0x0B):控制控制項重繪開關。

實作步驟

[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

public static void BeginUpdate(Control c) => SendMessage(c.Handle, 0x0B, IntPtr.Zero, IntPtr.Zero);
public static void EndUpdate(Control c) => SendMessage(c.Handle, 0x0B, (IntPtr)1, IntPtr.Zero);

後記:最大化視窗導致任務列消失問題

無邊框視窗從 Normal 切換至 Maximized(TopMost=true)時,控制項不閃爍正常,但任務列消失,背景色填充螢幕。原因:WM_SETREDRAW 影響了整個視窗層級,波及任務列重繪。

修正:強制任務列重繪

  1. 取得任務列視窗控制代碼:FindWindow("Shell_TrayWnd", "")。
  2. 呼叫 RedrawWindow 強制重繪(參考 Control.Invalidate 內部實作):
[DllImport("user32.dll")]
static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, uint flags);

const uint RDW_FRAME = 0x0400;
const uint RDW_INVALIDATE = 0x0001;
const uint RDW_ALLCHILDREN = 0x0080;

RedrawWindow(taskbarHandle, IntPtr.Zero, IntPtr.Zero, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);

後記二:Control 內建 BeginUpdateInternal

發現 Control 內部確有 BeginUpdateInternal 方法,但標記為 internal,僅 ListView 等少數控制項使用。微軟未公開此功能,需自行 P/Invoke 實作。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved