C#


キャプションバーのないプログラム #1

今回はキャプションバーのないプログラムについて扱います。 キャプションバーを消すだけなら、フォームのControlBoxプロパティにfalseを指定すればいいのですが、 消してしまうとフォームを動かすことができませんね?そこで、どうにかして動かす方法を考えようというわけです。
まずは素直にマウスイベントをオーバーライドする方法で解決を図りましょう。 例として、ボタンを押したら時間を表示するだけのプログラムを作ってみます。

001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

//2009/09/x Shirao //キャプションバーのないプログラムサンプル using System; using System.Drawing; using System.Windows.Forms; class NonCaptionMo : Form { //これも自動生成コード private Button button1; private Button button2; private TextBox textBox1; //メッセージを利用する方法 private const int WM_NCHITTEST = 0x84; //ポインタの動作を処理 private const int HTCLIENT = 0x1; //クライアント領域内にある private const int HTCAPTION = 0x2; //キャプションバー上にある //マウスのスクリーン座標 private Point ptMouseScreen = new Point(); public static void Main() { Application.Run(new NonCaptionMo()); } public NonCaptionMo() { InitializeComponent(); } #region Visual Studio 自動生成コード private void InitializeComponent() { this.textBox1 = new System.Windows.Forms.TextBox(); this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // textBox1 // this.textBox1.Location = new System.Drawing.Point(12, 12); this.textBox1.Name = "textBox1"; this.textBox1.ReadOnly = true; this.textBox1.Size = new System.Drawing.Size(268, 19); this.textBox1.TabIndex = 0; this.textBox1.Text = "時間"; // // button1 // this.button1.Location = new System.Drawing.Point(12, 37); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(120, 23); this.button1.TabIndex = 1; this.button1.Text = "時間表示"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // // button2 // this.button2.Location = new System.Drawing.Point(160, 37); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(120, 23); this.button2.TabIndex = 2; this.button2.Text = "消去"; this.button2.UseVisualStyleBackColor = true; this.button2.Click += new System.EventHandler(this.button2_Click); // // NonCaptionMo // this.ClientSize = new System.Drawing.Size(292, 72); this.ControlBox = false; this.Controls.Add(this.button2); this.Controls.Add(this.button1); this.Controls.Add(this.textBox1); this.KeyPreview = true; this.MaximumSize = new System.Drawing.Size(300, 80); this.MinimumSize = new System.Drawing.Size(300, 80); this.Name = "NonCaptionMo"; this.ShowInTaskbar = false; this.TopMost = true; this.ResumeLayout(false); this.PerformLayout(); } #endregion private void button1_Click(object sender, EventArgs e) { textBox1.Text = DateTime.Now.ToString(); } private void button2_Click(object sender, EventArgs e) { textBox1.Clear(); } #region マウス protected override void OnMouseDown(MouseEventArgs mea) { // マウスのスクリーン座標を取得する //Console.WriteLine(ptMouseScreen); ptMouseScreen = PointToScreen(new Point(mea.X, mea.Y)); base.OnMouseDown(mea); } protected override void OnMouseMove(MouseEventArgs mea) { // 移動中のマウスのスクリーン座標 Point nowPtMouseScreen = PointToScreen(new Point(mea.X, mea.Y)); if (mea.Button == MouseButtons.Left && //マウスの左ボタンは押されている ptMouseScreen != nowPtMouseScreen) //動いた { Location = new Point( Location.X + nowPtMouseScreen.X - ptMouseScreen.X, Location.Y + nowPtMouseScreen.Y - ptMouseScreen.Y); ptMouseScreen = nowPtMouseScreen; } base.OnMouseMove(mea); } #endregion }

ポイント

自動生成コード

行33から85と行10から12はVisualStudioの自動生成コードです。 #region#endregionで囲んでたたんでしまうと、いじることを推奨されない 部分を変更する事を防ぐことができます。あと、すっきりして見やすくなると思います。

マウスイベントのオーバーライド

マウスによるウィンドウの移動というものは、ドラッグすることで行います。 もっと言うと、マウスボタンを押して、それを離さずカーソルを移動し、目的位置で離すことで行います。 ということは、単純にはマウスボタンを押したときに位置を記憶し、押されたままで動いたときに その位置に逐次移動させると、移動は実現できるということになります。

OnMouseDown

これは次のようにオーバーライドします。ここでは、前述のように位置を記録します マウスの座標はPointToScreenでスクリーン座標で記録することに注意してください。

097 098 099 100 101 102 103

protected override void OnMouseDown(MouseEventArgs mea) { // マウスのスクリーン座標を取得する //Console.WriteLine(ptMouseScreen); ptMouseScreen = PointToScreen(new Point(mea.X, mea.Y)); base.OnMouseDown(mea); }

OnMouseMove

これはマウスが動いたときに呼び出されるので、これにはウィンドウを移動し、 位置を更新するという処理を実装します。
ウィンドウの移動はLocationに移動後の座標、つまり、移動元のマウスの座標に 変化量を足し合わせた座標を代入することでできます。 nowPtMouseScreenが現在の座標で、ptMouseScreen が移動元の座標です。
位置の更新は行116で行っています。

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119

protected override void OnMouseMove(MouseEventArgs mea) { // 移動中のマウスのスクリーン座標 Point nowPtMouseScreen = PointToScreen(new Point(mea.X, mea.Y)); if (mea.Button == MouseButtons.Left && //マウスの左ボタンは押されている ptMouseScreen != nowPtMouseScreen) //動いた { Location = new Point( Location.X + nowPtMouseScreen.X - ptMouseScreen.X, Location.Y + nowPtMouseScreen.Y - ptMouseScreen.Y); ptMouseScreen = nowPtMouseScreen; } base.OnMouseMove(mea); }

終了方法

コマンドラインプログラムとしてビルドしてるならコマンドラインでCtrl+cで終了。 あとは、Alt+F4でも終了できます。右クリックメニューやEscで終了できるようにするのがマナーではあると思いますが。

次回の布石

怪しげな定義がプログラム冒頭にありますね?これは次回扱うソリューションの布石です。 今回はいらないんですけどね。C++でWindowsプログラミングをした人にはあまりにもおなじみの方法ですね。

付録

ソース・実行ファイル

C#ソースコードと実行ファイルを置いておきます。


プログラムに戻る