如何在 Outlook Mailgrid 上设置 CustomControl?
我正在尝试使用 SetParent 设置对 Outlook Mailgrid 的控制,并调整大小(MoveWindow),并在 Mailgrid 更改时使其无效。
这是可行的,但是在调整大小时控件会开始闪烁。
My Control 是 Outlook Mailgrid 的替代品。要更改邮件预览,我只需通过控件更改原始邮件网格的选择。
我的控件的父窗口是 Outlook 主窗口。我已经尝试关闭 Mailgrid 窗口,但这没有帮助。
如果我将 Mailgrid 设置为父级,闪烁就会停止,但在这种情况下,如果我更改选择,它就会闪烁,并且不可能对邮件搜索窗口进行控制。
有人知道如何阻止极端闪烁吗?
处理 Outlook 邮件网格消息更改的类
sealed class SubWindow : NativeWindow
{
public event EventHandler Changed;
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)(NativEnums.WindowMessage.WM_SIZE) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGED) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGING) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_ERASEBKGND) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCHITTEST) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCCALCSIZE) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PAINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCPAINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PRINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PRINTCLIENT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_SETREDRAW) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_MOVE)
)
{
OnChanged();
}
base.WndProc(ref m);
//I have already tried to ignore wm_paint, but it still painted
//if (m.Msg != (int)NativEnums.WindowMessage.WM_PAINT)
//{
// base.WndProc(ref m);
//}
}
private void OnChanged()
{
if (Changed != null)
Changed(this, null);
}
}
创建事件侦听器和控件并设置其父级
//Is the Class above
SubWindow lw = new SubWindow();
lw.AssignHandle(ListHandle);
lw.Changed += new EventHandler(lw_Changed);
//Gets the IntPtr of the Mailgrid
//MainWindow is the Outlook main-window window
IntPtr ListHandle = GetSizes.GetMailFolderIntPtr(MainWindow);
//Gets the Rectangle of the Mailgrid
System.Drawing.Rectangle listsize = GetSizes.GetMailfolderSize(MainWindow, ListHandle);
//mc is the Custom Control
MoveWindow(mc.Handle, listsize.Left, listsize.Top, listsize.Width, listsize.Height, false);
SetParent(mc.Handle, MainWindow);
SetWindowLong(mc.Handle, (int)NativEnums.GetWindowLongConst.GWL_STYLE, (uint)(NativEnums.WindowStyles.WS_CHILD | NativEnums.WindowStyles.WS_VISIBLE));
更改事件绘制上
//Gets the Rectangle of the Mailgrid
System.Drawing.Rectangle listsize = GetSizes.GetMailfolderSize(MainWindow, ListHandle);
//Move and size the CustomControl to the Mailgrid Rectangle
MoveWindow(mc.Handle, listsize.Left, listsize.Top, listsize.Width, listsize.Height, false);
//Invalidate my Control
mc.Invalidate();
在我的控件的
protected override void OnPaint(PaintEventArgs e)
{
DoPaint(e.Graphics);
//base.OnPaint(e);
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
//base.OnPaintBackground(pevent);
}
public void DoPaint(Graphics g)
{
g.Clear(BackColor);
//Here comes the painting of the GridRows (only the visible rows)
}
/// 编辑
在添加 Thread.Sleep(1000)
到DoPaint 方法我能够看到绘画顺序。 调整大小后,我的控件会立即显示,然后 Outlook Mailgrid 会覆盖我的控件。 我尝试在 OnChange();
之前设置 base.WndProc(ref m);
但没有任何改变。 我希望这有助于解决问题。
/// 编辑
经过一些测试,我尝试监听所有 Outlook 窗口并将 Graphics.Clear 设为橙色。 我不知道为什么,但即使这样也不起作用。在调整大小时,几乎所有内容都是由前景绘制的。
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
/////////////////////////////////////////////////////
// Here i clear the complete window (all windows) //
/////////////////////////////////////////////////////
using (Graphics g = Graphics.FromHwnd(m.HWnd))
g.Clear(Color.Orange);
if (m.Msg == (int)(NativEnums.WindowMessage.WM_SIZE) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGED) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGING) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGING) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_ERASEBKGND) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCHITTEST) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCCALCSIZE) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PAINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCPAINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PRINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PRINTCLIENT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_SETREDRAW) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_MOVE)
)
{
OnChanged();
}
}
I'm trying to set my control over the Outlook Mailgrid with SetParent and resize (MoveWindow) and invalidate it if the Mailgrid changed.
This works, but on resize the control starts the flicker.
My Control is a replacement of Outlook's Mailgrid. To change the mailpreview i just change the selection of the original mailgrid via my control.
The Parent of my Control is the Outlook main-window. I have already tried to close the Mailgrid window, but that didn't help.
The flicker stops if I set the the Mailgrid as Parent, but in this case it flickers if i change the selection, and its not possible to draw my control over the mailsearch-window.
Does anybody know how to stop the extrem flicker?
Class to Handle changes of Outlook's Mailgrid Messages
sealed class SubWindow : NativeWindow
{
public event EventHandler Changed;
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)(NativEnums.WindowMessage.WM_SIZE) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGED) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGING) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_ERASEBKGND) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCHITTEST) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCCALCSIZE) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PAINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCPAINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PRINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PRINTCLIENT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_SETREDRAW) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_MOVE)
)
{
OnChanged();
}
base.WndProc(ref m);
//I have already tried to ignore wm_paint, but it still painted
//if (m.Msg != (int)NativEnums.WindowMessage.WM_PAINT)
//{
// base.WndProc(ref m);
//}
}
private void OnChanged()
{
if (Changed != null)
Changed(this, null);
}
}
Creating the Event-Listener and Control and set it's parent
//Is the Class above
SubWindow lw = new SubWindow();
lw.AssignHandle(ListHandle);
lw.Changed += new EventHandler(lw_Changed);
//Gets the IntPtr of the Mailgrid
//MainWindow is the Outlook main-window window
IntPtr ListHandle = GetSizes.GetMailFolderIntPtr(MainWindow);
//Gets the Rectangle of the Mailgrid
System.Drawing.Rectangle listsize = GetSizes.GetMailfolderSize(MainWindow, ListHandle);
//mc is the Custom Control
MoveWindow(mc.Handle, listsize.Left, listsize.Top, listsize.Width, listsize.Height, false);
SetParent(mc.Handle, MainWindow);
SetWindowLong(mc.Handle, (int)NativEnums.GetWindowLongConst.GWL_STYLE, (uint)(NativEnums.WindowStyles.WS_CHILD | NativEnums.WindowStyles.WS_VISIBLE));
On Change-Event
//Gets the Rectangle of the Mailgrid
System.Drawing.Rectangle listsize = GetSizes.GetMailfolderSize(MainWindow, ListHandle);
//Move and size the CustomControl to the Mailgrid Rectangle
MoveWindow(mc.Handle, listsize.Left, listsize.Top, listsize.Width, listsize.Height, false);
//Invalidate my Control
mc.Invalidate();
Painting of my Control
protected override void OnPaint(PaintEventArgs e)
{
DoPaint(e.Graphics);
//base.OnPaint(e);
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
//base.OnPaintBackground(pevent);
}
public void DoPaint(Graphics g)
{
g.Clear(BackColor);
//Here comes the painting of the GridRows (only the visible rows)
}
/// EDIT
After adding a Thread.Sleep(1000)
to the the DoPaint methode i was able to see the paint order.
After resizing, my control shows up for an instant, afterwards the Outlook Mailgrid overpaints my Control.
I've tried to set base.WndProc(ref m);
befor OnChange();
but nothing changed.
I hope this helps to resolve the problem.
/// EDIT
After some testing I've tried to listen to all outlook windows and Graphics.Clear
them orange.
I don't know why, but even this doesn't work. While resizing nearly everything is drawn by outlook.
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
/////////////////////////////////////////////////////
// Here i clear the complete window (all windows) //
/////////////////////////////////////////////////////
using (Graphics g = Graphics.FromHwnd(m.HWnd))
g.Clear(Color.Orange);
if (m.Msg == (int)(NativEnums.WindowMessage.WM_SIZE) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGED) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGING) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_WINDOWPOSCHANGING) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_ERASEBKGND) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCHITTEST) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCCALCSIZE) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PAINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_NCPAINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PRINT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_PRINTCLIENT) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_SETREDRAW) ||
m.Msg == (int)(NativEnums.WindowMessage.WM_MOVE)
)
{
OnChanged();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我通过将侦听器添加到 Outlook“Frame Splitter”解决了该问题。
由于某种原因,Outlook 将 Mailgrid 设置为不可见并直接在主窗口上绘制。 (主窗口没有收到任何窗口消息)
我现在还在
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGED
WM_SETREDRAW
上绘制我对主窗口的控制。I have solved the problem by adding the listener to the Outlook "Frame Splitter".
For some reason Outlook sets the Mailgrid invisible and paints direct on the main window. (the main window doesn't get any windowmessage)
I now also paint on
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGED
WM_SETREDRAW
my control over the main window.