📄 commandbar.cs
字号:
nextIndex = (nextIndex + 1) % count;
}
while ((nextIndex != index) && (!items[nextIndex].IsVisible));
return nextIndex;
}
private int GetPreviousItem(int index)
{
if (index < 0)
{
throw new ArgumentException("index");
}
int count = NativeMethods.SendMessage(this.Handle, NativeMethods.TB_BUTTONCOUNT, 0, 0);
int prevIndex = index;
do
{
prevIndex = (prevIndex + count - 1) % count;
}
while ((prevIndex != index) && (!items[prevIndex].IsVisible));
return prevIndex;
}
private int GetHotItem()
{
return NativeMethods.SendMessage(Handle, NativeMethods.TB_GETHOTITEM, 0, 0);
}
private void SetHotItem(int index)
{
NativeMethods.SendMessage(Handle, NativeMethods.TB_SETHOTITEM, index, 0);
}
private void SetState(State state, int index)
{
if (this.state != state)
{
if (state == State.None)
{
index = -1;
}
this.SetHotItem(index);
if (state == State.HotTracking)
{
this.trackEscapePressed = false;
this.trackHotItem = index;
}
}
this.lastState = this.state;
this.state = state;
}
private void TrackDropDownNext(int index)
{
if (index != this.trackHotItem)
{
NativeMethods.PostMessage(Handle, NativeMethods.WM_CANCELMODE, 0, 0);
this.trackNextItem = index;
}
}
private void TrackDropDown(int index)
{
while (index >= 0)
{
this.trackNextItem = -1;
this.BeginUpdate();
CommandBarMenu menu = this.items[index] as CommandBarMenu;
if (menu != null)
{
menu.PerformDropDown(EventArgs.Empty);
this.contextMenu.Items.Clear();
this.contextMenu.Items.AddRange(menu.Items); // = menu.Items;
this.contextMenu.Mnemonics = true;
}
else
{
this.contextMenu.Items.Clear(); // .Items = new CommandBarItemCollection();
this.contextMenu.Mnemonics = true;
}
// Item state
NativeMethods.SendMessage(this.Handle, NativeMethods.TB_PRESSBUTTON, index, -1);
// Trick to get the first menu item selected
NativeMethods.PostMessage(this.Handle, NativeMethods.WM_KEYDOWN, (int) Keys.Down, 1);
NativeMethods.PostMessage(this.Handle, NativeMethods.WM_KEYUP, (int) Keys.Down, 1);
this.SetState(State.HotTracking, index);
// Hook
NativeMethods.HookProc hookProc = new NativeMethods.HookProc(DropDownHook);
GCHandle hookProcHandle = GCHandle.Alloc(hookProc);
this.hookHandle = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MSGFILTER, hookProc, IntPtr.Zero, NativeMethods.GetCurrentThreadId());
if (this.hookHandle == IntPtr.Zero)
{
throw new SecurityException();
}
// Ask for position
NativeMethods.RECT rect = new NativeMethods.RECT();
NativeMethods.SendMessage(Handle, NativeMethods.TB_GETRECT, index, ref rect);
Point position = new Point(rect.left, rect.bottom);
this.EndUpdate();
this.Update();
this.contextMenu.Show(this, position);
// Unhook
NativeMethods.UnhookWindowsHookEx(hookHandle);
hookProcHandle.Free();
this.hookHandle = IntPtr.Zero;
// Item state
NativeMethods.SendMessage(Handle, NativeMethods.TB_PRESSBUTTON, index, 0);
this.SetState(trackEscapePressed ? State.Hot : State.None, index);
index = trackNextItem;
}
}
public void Show(Control control, Point point)
{
CommandBarItemCollection chevronItems = new CommandBarItemCollection();
Size size = ClientSize;
for (int i = 0; i < items.Count; i++)
{
NativeMethods.RECT rect = new NativeMethods.RECT();
NativeMethods.SendMessage(Handle, NativeMethods.TB_GETITEMRECT, i, ref rect);
if (rect.right > size.Width)
{
CommandBarItem item = items[i];
if (item.IsVisible)
{
if ((!(item is CommandBarSeparator)) || (chevronItems.Count != 0))
chevronItems.Add(item);
}
}
}
this.contextMenu.Mnemonics = false;
this.contextMenu.Items.Clear();
this.contextMenu.Items.AddRange(chevronItems);
this.contextMenu.Show(control, point);
}
private bool DropDownFilter(ref Message message)
{
if (state != State.HotTracking)
{
throw new InvalidOperationException();
}
// comctl32 sometimes steals the hot item for unknown reasons.
this.SetHotItem(this.trackHotItem);
if (message.Msg == NativeMethods.WM_KEYDOWN)
{
Keys keyData = (Keys)(int) message.WParam | ModifierKeys;
if (keyData == Keys.Left)
{
this.TrackDropDownNext(this.GetPreviousItem(trackHotItem));
return true;
}
// Only move right if there is no submenu on the current selected item.
if ((keyData == Keys.Right) && ((this.contextMenu.SelectedMenuItem == null) || (this.contextMenu.SelectedMenuItem.MenuItems.Count == 0)))
{
this.TrackDropDownNext(GetNextItem(trackHotItem));
return true;
}
if (keyData == Keys.Escape)
{
trackEscapePressed = true;
}
}
else if ((message.Msg == NativeMethods.WM_MOUSEMOVE) || (message.Msg == NativeMethods.WM_LBUTTONDOWN))
{
Point point = new Point(((int) message.LParam) & 0xffff, ((int) message.LParam) >> 16);
point = this.PointToClient(point);
if (message.Msg == NativeMethods.WM_MOUSEMOVE)
{
if (point != lastMousePosition)
{
int index = HitTest(point);
if ((this.IsValid(index)) && (index != trackHotItem))
this.TrackDropDownNext(index);
lastMousePosition = point;
}
}
else if (message.Msg == NativeMethods.WM_LBUTTONDOWN)
{
if (HitTest(point) == trackHotItem)
{
this.TrackDropDownNext(-1);
return true;
}
}
}
return false;
}
private IntPtr DropDownHook(int code, IntPtr wparam, IntPtr lparam)
{
if (code == NativeMethods.MSGF_MENU)
{
NativeMethods.MSG msg = (NativeMethods.MSG) Marshal.PtrToStructure(lparam, typeof(NativeMethods.MSG));
Message message = Message.Create(msg.hwnd, msg.message, msg.wParam, msg.lParam);
if (this.DropDownFilter(ref message))
{
return (IntPtr)1;
}
}
return NativeMethods.CallNextHookEx(this.hookHandle, code, wparam, lparam);
}
[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message message)
{
base.WndProc(ref message);
switch (message.Msg)
{
case NativeMethods.WM_COMMAND + NativeMethods.WM_REFLECT:
int index = (int) message.WParam & 0xFFFF;
this.PerformClick(this.items[index]);
base.WndProc(ref message);
this.ResetMouseEventArgs();
break;
case NativeMethods.WM_MENUCHAR:
this.WmMenuChar(ref message);
break;
case NativeMethods.WM_NOTIFY:
case NativeMethods.WM_NOTIFY + NativeMethods.WM_REFLECT:
NativeMethods.NMHDR note = (NativeMethods.NMHDR) message.GetLParam(typeof(NativeMethods.NMHDR));
switch (note.code)
{
case NativeMethods.TTN_NEEDTEXTA:
NotifyNeedTextA(ref message);
break;
case NativeMethods.TTN_NEEDTEXTW:
NotifyNeedTextW(ref message);
break;
case NativeMethods.TBN_QUERYINSERT:
message.Result = (IntPtr) 1;
break;
case NativeMethods.TBN_DROPDOWN:
this.NotifyDropDown(ref message);
break;
case NativeMethods.NM_CUSTOMDRAW:
this.NotifyCustomDraw(ref message);
break;
case NativeMethods.TBN_HOTITEMCHANGE:
break;
}
break;
}
}
private void NotifyCustomDrawMenuBar(ref Message m)
{
m.Result = (IntPtr) NativeMethods.CDRF_DODEFAULT;
NativeMethods.LPNMTBCUSTOMDRAW tbcd = (NativeMethods.LPNMTBCUSTOMDRAW) m.GetLParam(typeof(NativeMethods.LPNMTBCUSTOMDRAW));
bool hot = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_HOT) != 0);
bool selected = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_SELECTED) != 0);
if (hot || selected)
{
NativeMethods.RECT rect = tbcd.nmcd.rc;
using (Graphics graphics = Graphics.FromHdc(tbcd.nmcd.hdc))
{
graphics.FillRectangle(SystemBrushes.Highlight, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
}
using (TextGraphics textGraphics = new TextGraphics(tbcd.nmcd.hdc))
{
Font font = this.Font;
string text = this.items[tbcd.nmcd.dwItemSpec].Text;
Size size = textGraphics.MeasureText(text, font);
Point point = new Point(rect.left + ((rect.right - rect.left - size.Width) / 2), rect.top + ((rect.bottom - rect.top - size.Height) / 2));
textGraphics.DrawText(text, point, font, SystemColors.HighlightText);
}
m.Result = (IntPtr) NativeMethods.CDRF_SKIPDEFAULT;
}
}
private void NotifyCustomDrawToolBar(ref Message m)
{
m.Result = (IntPtr) NativeMethods.CDRF_DODEFAULT;
NativeMethods.DLLVERSIONINFO dvi = new NativeMethods.DLLVERSIONINFO();
dvi.cbSize = Marshal.SizeOf(typeof(NativeMethods.DLLVERSIONINFO));
NativeMethods.DllGetVersion(ref dvi);
if (dvi.dwMajorVersion < 6)
{
NativeMethods.LPNMTBCUSTOMDRAW tbcd = (NativeMethods.LPNMTBCUSTOMDRAW)m.GetLParam(typeof(NativeMethods.LPNMTBCUSTOMDRAW));
NativeMethods.RECT rc = tbcd.nmcd.rc;
Rectangle rectangle = new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
//// Alex:graphics and image must be released - lots of calls
using (Graphics graphics = Graphics.FromHdc(tbcd.nmcd.hdc)) {
CommandBarItem item = items[tbcd.nmcd.dwItemSpec];
bool hot = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_HOT) != 0);
bool selected = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_SELECTED) != 0);
bool disabled = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_DISABLED) != 0);
CommandBarCheckBox checkBox = item as CommandBarCheckBox;
if ((checkBox != null) && (checkBox.IsChecked))
{
ControlPaint.DrawBorder3D(graphics, rectangle, Border3DStyle.SunkenOuter);
}
else if (selected)
{
ControlPaint.DrawBorder3D(graphics, rectangle, Border3DStyle.SunkenOuter);
}
else if (hot)
{
ControlPaint.DrawBorder3D(graphics, rectangle, Border3DStyle.RaisedInner);
}
//// Alex: don't create references unnecessarily - lots of calls
if (item.Image != null)
{
Size size = item.Image.Size;
Point point = new Point(rc.left + ((rc.right - rc.left - size.Width) / 2), rc.top + ((rc.bottom - rc.top - size.Height) / 2));
NativeMethods.DrawImage(graphics, item.Image, point, disabled);
}
}
m.Result = (IntPtr)NativeMethods.CDRF_SKIPDEFAULT;
}
}
private void NotifyCustomDraw(ref Message m)
{
m.Result = (IntPtr) NativeMethods.CDRF_DODEFAULT;
NativeMethods.LPNMTBCUSTOMDRAW tbcd = (NativeMethods.LPNMTBCUSTOMDRAW) m.GetLParam(typeof(NativeMethods.LPNMTBCUSTOMDRAW));
switch (tbcd.nmcd.dwDrawStage)
{
case NativeMethods.CDDS_PREPAINT:
m.Result = (IntPtr) NativeMethods.CDRF_NOTIFYITEMDRAW;
break;
case NativeMethods.CDDS_ITEMPREPAINT:
if (this.style == CommandBarStyle.Menu)
{
this.NotifyCustomDrawMenuBar(ref m);
}
if (this.style == CommandBarStyle.ToolBar)
{
this.NotifyCustomDrawToolBar(ref m);
}
break;
}
}
private void WmMenuChar(ref Message message)
{
Menu menu = contextMenu.FindMenuItem(MenuItem.FindHandle, message.LParam);
if (contextMenu.Handle == message.LParam)
{
menu = contextMenu;
}
if (menu != null)
{
char key = char.ToUpper((char) ((int) message.WParam & 0x0000FFFF), CultureInfo.InvariantCulture);
int index = 0;
foreach (MenuItem menuItem in menu.MenuItems)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -