winform之在主窗體中不顯示子窗體的選單欄

来个火龙果發表於2024-04-20

在MDi窗體嵌入子窗體後不顯示選單欄

背景:

由於之前做的一個程式的功能全部都是放在一個介面上的,有一個功能能夠在資料庫查詢資料,並返回到介面上,資料量比較小的時候還好,但是資料量多了,導致它阻塞的其他執行緒,經過一系列討論之後,決定將一個介面換成一個主介面加多個子介面。

實施:

多個子介面遷移完成之後,使用下面的方法將其放置的主介面中(先將主窗體的IsMdiContainer設定為true,不然會報錯)

Form frm = new SssForm();
foreach (Form childForm in MdiChildren)
{
    if (childForm != CccForm)
    {
        childForm.Close();
    }
}
this.CccForm.Visible = false;
frm.MdiParent = this;
frm.Show();
frm.WindowState = FormWindowState.Maximized;

然後在主窗體和子窗體的屬性那裡把ControlBox屬性設定為false,然後測試發現主窗體一開始是沒有選單欄的,但是開啟子窗體之後就會在主窗體的右上角顯示出選單欄

查閱了一些網上的辦法去改變其他屬性值,但是測試之後發現沒有用,有說用pannel的,但是我的這個程式需要在Mdi中實現,就沒有去實踐了,後面就去問gpt4了,最後用gpt4給的方法實現了

這個方法是重寫WndProc,在獲取到子窗體需要重新計算大小時,直接告訴系統我們只需要計算工作區,而不需要把選單欄加入進來,這裡微軟的官方文件裡面也有寫到[(https://learn.microsoft.com/zh-cn/windows/win32/winmsg/wm-nccalcsize)]

以下是程式碼實現:

protected override void WndProc(ref Message m)
{
    const int WM_NCCALCSIZE = 0x0083;
    const int WM_NCHITTEST = 0x0084;

    switch (m.Msg)
    {
        case WM_NCCALCSIZE:
            // 當窗體的大小需要重新計算時,系統會傳送WM_NCCALCSIZE訊息
            // 這裡可以修改訊息的處理,以改變窗體非客戶區的大小
            // 如果wParam是TRUE(非零),則指示客戶區大小需要重新計算
            // 透過簡單地返回0,我們可以告訴Windows我們已處理訊息,不需要預設的非客戶區
            // 這實際上會移除所有的非客戶區,包括邊框和標題欄
            if (m.WParam.ToInt32() != 0)
            {
                // 返回0表示我們處理了這個訊息,不再需要預設的處理
                // 這將去除非客戶區,包括標題欄和邊框
                m.Result = IntPtr.Zero;
                return;
            }
            break;
        case WM_NCHITTEST:
            // 可以在這裡處理滑鼠事件,例如檢測滑鼠是否在我們自定義的標題欄區域內
            // 這對於新增拖動行為等自定義互動是有用的
            base.WndProc(ref m);
            if ((int)m.Result == 0x01) // HTCLIENT
            {
                // 可以修改m.Result來改變滑鼠的行為,例如使其支
                // m.Result = (IntPtr)2; // HTCAPTION 表示標題欄,允許拖動窗體
            }
            return;
    }
    base.WndProc(ref m);
}

然後根據我想要的功能給它簡單的最佳化了一些

protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x0083 && m.WParam.ToInt32() != 0)
    {
        m.Result = IntPtr.Zero;
        return;
    }
    base.WndProc(ref m);
}

效果圖:

相關文章