在表格区域外绘图时如何重绘

时间:2016-06-26 00:32:07

标签: c# windows winforms winapi graphics

我正在编写一个需要在其主窗口区域之外绘制的应用程序。我已经编写代码来实际绘图:

[DllImport("User32.dll")]
public static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("User32.dll")]
public static extern void ReleaseDC(IntPtr hwnd, IntPtr dc);

IntPtr desktopPtr = GetDC(IntPtr.Zero);
Graphics g = Graphics.FromHdc(desktopPtr);

g.DrawLine(Pens.White, 0, 0, Screen.FromControl(this).WorkingArea.Width, Screen.FromControl(this).WorkingArea.Height);

g.Dispose();
ReleaseDC(IntPtr.Zero, desktopPtr);

然而,on paint事件是一个不适合放置代码的地方,因为当重绘表单之外的东西时它不会被调用。所以我的问题是,这个代码放在哪里,以便在重绘部分屏幕时调用它?

1 个答案:

答案 0 :(得分:2)

如果您想在屏幕上绘制内容,则应始终创建一个窗口来保存该内容。在桌面上绘画(一个你不拥有的窗口)是一个坏主意。

解决方案是使用扩展样式<div class="ui-accordion-title" ng-click="open()"> {{username | name | elipsis:14}} </div> <div class="ui-accordion-content" ng-show="isOpened"> <div class="form-group"> <div class="input-group"> <span class="input-group-addon" id="nome-addon"><strong>Nome</strong></span> <input class="form-control" type="text" ng-model="nome" disabled="" value="{{username | name}}" aria-describedby="nome-addon"> </div> </div> (others divs and inputs....) </div> 创建一个窗口,并在其上绘制以响应WS_EX_NOACTIVATE消息。对于WinForms应用程序,当您获得WM_PAINT时,运行时会调用Form.OnPaint,以便您可以处理该事件并在那里进行绘制。为了证明:

WM_PAINT

如果您希望窗口浮动在顶部,请将表单的[DllImport("User32.dll")] private static extern IntPtr GetWindowLong(IntPtr hWnd, int index); [DllImport("User32.dll")] private static extern int SetWindowLong(IntPtr hWnd, int index, IntPtr value); [DllImport("User32.dll")] private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); static readonly IntPtr HWND_BOTTOM = new IntPtr(1); private const int WS_EX_NOACTIVATE = 0x08000000; private const int GWL_EXSTYLE = -20; private const uint SWP_NOMOVE = 0x0002; private const uint SWP_NOSIZE = 0x0001; private const uint SWP_NOZORDER = 0x0004; private const uint SWP_FRAMECHANGED = 0x0020; private const uint StyleUpdateFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED; public Form1() { InitializeComponent(); this.FormBorderStyle = FormBorderStyle.None; this.Paint += Form1_Paint; this.Shown += Form1_Shown; } private void Form1_Shown(object sender, EventArgs e) { IntPtr currentStyle = GetWindowLong(this.Handle, GWL_EXSTYLE); int current = currentStyle.ToInt32(); current |= WS_EX_NOACTIVATE; SetWindowLong(this.Handle, GWL_EXSTYLE, new IntPtr(current)); SetWindowPos(this.Handle, IntPtr.Zero, 0, 0, 0, 0, StyleUpdateFlags); } private void Form1_Paint(object sender, PaintEventArgs e) { e.Graphics.Clear(Color.Black); } 属性设置为true。如果您希望窗口粘贴在Z-Order的底部(与TopMost完全相反),则将以下逻辑添加到表单中:

TopMost

这会处理private struct WINDOWPOS { public IntPtr hwnd; public IntPtr hwndInsertAfter; public int x; public int y; public int cx; public int cy; public uint flags; } private const int WM_WINDOWPOSCHANGING = 0x0046; protected override void WndProc(ref Message m) { if (m.Msg == WM_WINDOWPOSCHANGING) { if (m.LParam != IntPtr.Zero) { WINDOWPOS posInfo = Marshal.PtrToStructure<WINDOWPOS>(m.LParam); posInfo.hwndInsertAfter = HWND_BOTTOM; Marshal.StructureToPtr(posInfo, m.LParam, true); m.Result = IntPtr.Zero; return; } } base.WndProc(ref m); } 窗口消息,并通过告诉窗口管理器将窗口放在底部来防止窗口在Z-Order中向上移动。