在視窗標題欄上加按鈕本來不是什麼新鮮事了,我在vc++下早也實現過了(相信很多人也都實現過了)。今天乙個朋友問我c# winform下可否實現,我就順便拿c#寫了乙個。
原理是一樣的,都是重寫視窗過程(wndproc),處理一些非客戶區訊息(wm_nc***x),可以說本來沒有什麼新意,可是從寫這個程式的過程中,我也學到了兩個技巧:
1)、c#中重寫視窗過程不用再呼叫setwindowlong api了,直接overide乙個wndproc就可以了。
2)、windows api中的hdc可以通過graphics.fromhdc()轉換為(建立出)system.drawing.graphics,然後就可以用.net framework (gid+??)提供的繪圖功能方便地進行畫圖了。終於可以拋開討厭的gdi api了(說實在話,在c#中呼叫windows api真的太麻煩了:)).
**如下:
using system;
using system.drawing;
using system.drawing.drawing2d;
using system.collections;
using system.componentmodel;
using system.windows.forms;
using system.data;
using system.runtime.interopservices;
using system.diagnostics;
///
/// form1 的摘要說明。
///
public class form1 : system.windows.forms.form
///
/// 必需的設計器變數。
///
private system.componentmodel.container components = null;
public form1()
// windows 窗體設計器支援所必需的
initializecomponent();
// todo: 在 initializecomponent 呼叫後新增任何建構函式**
///
/// 清理所有正在使用的資源。
///
protected override void dispose( bool disposing )
if( disposing )
if (components != null)
components.dispose();
base.dispose( disposing );
#region windows 窗體設計器生成的**
///
/// 設計器支援所需的方法 - 不要使用**編輯器修改
/// 此方法的內容。
///
private void initializecomponent()
// form1
this.autoscalebasesize = new system.drawing.size(6, 14);
this.clientsize = new system.drawing.size(292, 266);
this.name = "form1";
this.text = "form1";
this.sizechanged += new system.eventhandler(this.form1_sizechanged);
#endregion
///
/// 應用程式的主入口點。
///
[stathread]
static void main()
[dllimport ("user32.dll")]
private static extern intptr getwindowdc(intptr hwnd);
[dllimport ("user32.dll")]
private static extern int releasedc(intptr hwnd, intptr hdc);
[dllimport ("kernel32.dll")]
private static extern int getlasterror();
//標題欄按鈕的矩形區域。
rectangle m_rect = new rectangle(205, 6, 20, 20);
protected override void wndproc(ref message m)
base.wndproc(ref m);
switch(m.msg)
case 0x86://wm_ncactivate
goto case 0x85;
case 0x85://wm_ncpaint
intptr hdc = getwindowdc(m.hwnd);
//把dc轉換為.net的graphics就可以很方便地使用framework提供的繪圖功能了
graphics gs = graphics.fromhdc(hdc);
gs.fillrectangle(new lineargradientbrush(m_rect, color.pink, color.purple, lineargradientmode.backwarddiagonal), m_rect);
stringformat strfmt = new stringformat();
strfmt.alignment = stringalignment.center;
strfmt.linealignment = stringalignment.center;
gs.drawstring("√", this.font, brushes.blanchedalmond, m_rect, strfmt);
gs.dispose();
//釋放gdi資源
releasedc(m.hwnd, hdc);
break;
case 0xa1://wm_nclbuttondown
point mousepoint = new point((int)m.lparam);
mousepoint.offset(-this.left, -this.top);
if(m_rect.contains(mousepoint))
messagebox.show("hello");
break;
//在視窗大小改變時及時更新按鈕的區域。
private void form1_sizechanged(object sender, system.eventargs e)
m_rect.x = this.bounds.width - 95;
m_rect.y = 6;
m_rect.width = m_rect.height = 20;
C WinForm 中在視窗標題欄上加按鈕
在視窗標題欄上加按鈕本來不是什麼新鮮事了,我在vc 下早也實現過了 相信很多人也都實現過了 今天乙個朋友問我c winform下可否實現,我就順便拿c 寫了乙個。原理是一樣的,都是重寫視窗過程 wndproc 處理一些非客戶區訊息 wm nc x 可以說本來沒有什麼新意,可是從寫這個程式的過程中,我...
C WinForm 中在視窗標題欄上加按鈕 轉
system using system.drawing using system.drawing.drawing2d using system.collections using system.componentmodel using system.windows.forms using syste...
移動無標題欄視窗
一般情況下,移動乙個窗體需要將滑鼠放置在標題欄上才能拖動窗體,為 什麼非要使用標題欄呢?其實我們可以使用乙個巧妙的方法來實現將滑鼠放置 在窗體上按下就可拖動窗體,下面先看實現 在form1的 private 部分宣告過程 在private部分加入下列 procedure wmnchittest va...