Как я могу открыть системное меню окна по коду? - PullRequest
4 голосов
/ 26 сентября 2008

У меня есть окно C # WinForms без полей, для которого я переопределяю WndProc и обрабатываю сообщение WM_NCHITTEST. Для области этой формы моя функция проверки попадания возвращает HTSYSMENU. Двойной щелчок по этой области успешно закрывает форму, но при щелчке правой кнопкой мыши по ней не отображается системное меню окна и не отображается при щелчке правой кнопкой мыши по имени окна на панели задач.

В этой форме используются следующие стили:

this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );
this.SetStyle( ControlStyles.UserPaint, true );
this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );
this.SetStyle( ControlStyles.ResizeRedraw, true );

И имеет следующие значения свойств не по умолчанию:

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.KeyPreview = true;
this.MaximizeBox = false;
this.MinimizeBox = false;

Я попытался обработать WM_NCRBUTTONDOWN и WM_NCRBUTTONUP и отправить сообщение WM_GETSYSMENU, но это не сработало.

Ответы [ 3 ]

5 голосов
/ 02 октября 2008

Окно без полей, если я не ошибаюсь, помечается так, что оно не предлагает системного меню и не отображается на панели задач.

Тот факт, что любое окно не имеет границы и не отображается на панели задач, является результатом установки флагов стиля в окне. Эти конкретные флаги стиля можно установить с помощью вызовов API GetWindowLong и SetWindowLong. Однако вы должны быть осторожны, так как некоторые стили просто не работают вместе.

Я написал несколько пользовательских элементов управления за эти годы, и я постоянно уговариваю окна стать такими, какими они изначально не были.
Например, я написал свой собственный выпадающий элемент управления, в котором мне нужно окно, которое будет вести себя как всплывающее окно, а не активироваться.
Следующий код сделает это. Обратите внимание, что код появляется в обработчике событий OnHandleCreated. Это связано с тем, что флаги необходимо изменить сразу после установки дескриптора, который указывает, что Windows уже установила то, что, по ее мнению, должны быть флагами.

using System.Runtime.InteropServices;

protected override void OnHandleCreated(EventArgs e) {
    uint dwWindowProperty;

    User32.SetParent(this.Handle, IntPtr.Zero);

    dwWindowProperty = User32.GetWindowLong( this.Handle, User32.GWL.EXSTYLE );
    dwWindowProperty = dwWindowProperty | (uint)User32.WSEX.TOOLWINDOW | (uint)User32.WSEX.NOACTIVATE;
    User32.SetWindowLong( this.Handle, User32.GWL.EXSTYLE, dwWindowProperty );

    dwWindowProperty = User32.GetWindowLong( this.Handle, User32.GWL.STYLE );
    dwWindowProperty = ( dwWindowProperty & ~(uint)User32.WS.CHILD ) | (uint)User32.WS.POPUP; 
    User32.SetWindowLong( this.Handle, User32.GWL.STYLE, dwWindowProperty );
    base.OnHandleCreated (e);
}


//this is a fragment of my User32 library wrapper needed for the previous code segment.
class User32 
{
    [DllImport("user32.dll", SetLastError = true)]
   static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall )]
    public  static extern int SetWindowLong( IntPtr hWnd, User32.GWL gwlIndex, uint dwNewLong); 

    [DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall )]
    public static extern uint GetWindowLong( IntPtr hWnd, User32.GWL gwlIndex );

    [FlagsAttribute] 
    public enum WS: uint { 
        POPUP = 0x80000000,
        CHILD = 0x40000000,
    }

    public enum GWL {
        STYLE   = -16,
        EXSTYLE = -20
    }

    [FlagsAttribute]
    public enum WSEX: uint {
        TOP        = 0x0,
        TOPMOST    = 0x8,
        TOOLWINDOW = 0x80,
        NOACTIVATE = 0x08000000,
    }
}

К сожалению, стиль SysMenu нельзя установить без использования стиля Caption, поэтому я не могу сказать, является ли это проблемой в вашей реализации.

Вы можете проверить исходный список стилей и список расширенных стилей по этим двум ссылкам:
Стили окон
CreateWindowEx

0 голосов
/ 16 января 2009
    protected override void WndProc( ref System.Windows.Forms.Message m )
    { // RightClickMenu
        if ( m.Msg == 0x313 )
        {
            this.contextMenuStrip1.Show(this, this.PointToClient(new Point(m.LParam.ToInt32())));
        }}

Определяет щелчок правой кнопкой мыши на "области" панели задач приложения.

может это поможет?

0 голосов
/ 26 сентября 2008

У меня в приложении те же свойства, и щелчок правой кнопкой мыши тоже не работает, так что это не ваша проблема , похоже, что формы окон реагируют, когда у них нет границы.

Если вы установите для своей границы нормальное значение, вы сможете щелкнуть правой кнопкой мыши на панели задач и тому подобное.

Чтобы щелкнуть правой кнопкой мыши другие элементы управления, вам нужно установить ContextMenuStrip и указать свое «меню». Но я не уверен, если это работает, когда у вас есть без границ. Я не смог заставить его работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...