C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: フォーム最大化のキャンセル方法


(過去ログ 123 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■73348 / inTopicNo.1)  フォーム最大化のキャンセル方法
  
□投稿者/ ビール呑み (1回)-(2014/09/15(Mon) 20:52:53)

分類:[VB.NET/VB2005 以降] 

2014/09/15(Mon) 21:00:46 編集(投稿者)
web上のリソースを参考にvb.netプログラムの勉強をVS2010で始めたところでございます。
(.NETバージョン:指定なしだがとりあえず4.0)

次のような要件でウィンドウプログラムを作成し、目論見通りうまく動作しました。

・タイトルバーは表示しない(FormBorderStyle=none)
・最大化/最小化ボタンは不要(MaximizeBox=False, MinimizeBox=False)
・フォームの移動は、フォーム上の任意の位置をドラッグ&ドロップしておこなう。
(以下のコードを記述)

    <System.Security.Permissions.SecurityPermission( _
        System.Security.Permissions.SecurityAction.LinkDemand, _
        Flags:=System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)> _
    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)

        Const WM_NCHITTEST As Integer = &H84
        Const HTCLIENT As Integer = 1
        Const HTCAPTION As Integer = 2

        If m.Msg = WM_NCHITTEST And m.Result.ToInt32() = HTCLIENT Then
            m.Result = New IntPtr(HTCAPTION)
        End If
    End Sub

ところが、この場合フォーム上の任意の位置をダブルクリックすると、フォームが最大化表示されてしまいます。

WndProcに渡されるメッセージを一通り確認しましたが、「フォーム最大化」を
単独で意味すると思われるものは見当たらず、またWM_SYSCOMMANDや
WM_NCLBUTTONDBLCLKが渡される前に既に最大化されてしまうようです。

ダブルクリックした場合には特定の処理を実行し、なおかつ最大化はキャンセル
したいのですが、フォーム最大化の命令を捕捉してキャンセルするといった処理は
難しいのでしょうか?

有識者の方のご意見を参考にさせていただければと思います。よろしくお願い
いたします。m(_ _)m

引用返信 編集キー/
■73349 / inTopicNo.2)  Re[1]: フォーム最大化のキャンセル方法
□投稿者/ 魔界の仮面弁士 (123回)-(2014/09/15(Mon) 23:55:03)
No73348 (ビール呑み さん) に返信
> web上のリソースを参考にvb.netプログラムの勉強をVS2010で始めたところでございます。
And ではなく AndAlso を…というのは些末な話として:


> ダブルクリックした場合には特定の処理を実行し、なおかつ最大化はキャンセル
> したいのですが、フォーム最大化の命令を捕捉してキャンセルするといった処理は
> 難しいのでしょうか?

HTCLIENT のままにしておけば、そもそも通常通り DoubleClick イベントが発生します。
HTCAPTION として扱ってしまっているが故に、話を難しくしてしまっているように思えます。


> ダブルクリックすると、フォームが最大化表示されてしまいます。
これを止めるだけならば、
 Protected Overrides Sub WndProc(ByRef m As Message)
  If m.Msg = &H24 Then 'WM_GETMINMAXINFO
   Dim rect As Rectangle = Me.DesktopBounds
   Marshal.WriteInt32(m.LParam, 8, rect.Width)
   Marshal.WriteInt32(m.LParam, 12, rect.Height)
   Marshal.WriteInt32(m.LParam, 16, rect.Left)
   Marshal.WriteInt32(m.LParam, 20, rect.Top)
   Marshal.WriteInt32(m.LParam, 24, SystemInformation.MinWindowTrackSize.Width)
   Marshal.WriteInt32(m.LParam, 28, SystemInformation.MinWindowTrackSize.Height)
   Marshal.WriteInt32(m.LParam, 32, SystemInformation.MaxWindowTrackSize.Width)
   Marshal.WriteInt32(m.LParam, 36, SystemInformation.MaxWindowTrackSize.Height)
   m.Result = IntPtr.Zero
などという方法もありますが、「ダブルクリックされた時の処理」を
残したいのであれば、そもそも、HTCAPTION への変換を止めた方が良いでしょう。



WndProc のオーバーライドを行わず、移動処理のみを実装してみました。


Public Class Form1
  Private Sub Form1_DoubleClick(sender As Object, e As EventArgs) Handles Me.DoubleClick
    MsgBox("Double Clicked!") 'ダブルクリック時に処理させたい内容
  End Sub

  Private mouseDownPoint As Point? = Nothing 'ドラッグ開始座標
  Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    If (e.Button And MouseButtons.Left) = MouseButtons.Left Then
      mouseDownPoint = e.Location
    End If
  End Sub

  Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
    If (e.Button And MouseButtons.Left) = MouseButtons.Left Then
      mouseDownPoint = Nothing 'ドラッグ終了
    End If
  End Sub

  Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    If mouseDownPoint.HasValue Then
      'ドラッグで座標移動
      Dim pos As Point = Me.Location
      pos.Offset(e.Location - mouseDownPoint.Value)
      Me.Location = pos
    End If
  End Sub
End Class

引用返信 編集キー/
■73356 / inTopicNo.3)  Re[2]: フォーム最大化のキャンセル方法
□投稿者/ ビール呑み (3回)-(2014/09/16(Tue) 19:30:53)
No73349 (魔界の仮面弁士 さん) に返信

迅速なご返信、ありがとうございます。またこちらからの返信が遅くなり、申し訳ありません。

> HTCAPTION として扱ってしまっているが故に、話を難しくしてしまっているように思えます。

仰る通りだと思います。

ただ、ウィンドウの移動という低レベルな処理のために複数のイベントプロシージャを
記述するというのが可読性・汎用性の点でいかがなものかという思いもあり、
WndProcの中でメッセージを処理して対応するというアイデア(別に私のアイデアという
わけではないですが…)が捨てきれずに悶々としております。

お示しいただいた
>  Protected Overrides Sub WndProc(ByRef m As Message)
>   If m.Msg = &H24 Then 'WM_GETMINMAXINFO
>    Dim rect As Rectangle = Me.DesktopBounds
>    Marshal.WriteInt32(m.LParam, 8, rect.Width)
>    Marshal.WriteInt32(m.LParam, 12, rect.Height)
>    Marshal.WriteInt32(m.LParam, 16, rect.Left)
>    Marshal.WriteInt32(m.LParam, 20, rect.Top)
>    Marshal.WriteInt32(m.LParam, 24, SystemInformation.MinWindowTrackSize.Width)
>    Marshal.WriteInt32(m.LParam, 28, SystemInformation.MinWindowTrackSize.Height)
>    Marshal.WriteInt32(m.LParam, 32, SystemInformation.MaxWindowTrackSize.Width)
>    Marshal.WriteInt32(m.LParam, 36, SystemInformation.MaxWindowTrackSize.Height)
>    m.Result = IntPtr.Zero
という記述は、「サイズ変更されそうになったらサイズを設定し返す」というアプローチかと
思いますが、もっとダイレクトに「最大化を禁止」「最大化をキャンセル」といった方法論は
ないものでしょうか?

(「あるに違いない」という思い込みだけで3連休を棒に振っているので、「んなものは無い」と
ひとこと言っていただければ踏ん切りもつくのですが…)

>>web上のリソースを参考にvb.netプログラムの勉強をVS2010で始めたところでございます。
> And ではなく AndAlso を…というのは些末な話として:

?????
すみません、わからないので解説いただけると幸いです。


引用返信 編集キー/
■73357 / inTopicNo.4)  Re[3]: フォーム最大化のキャンセル方法
□投稿者/ ビール呑み (4回)-(2014/09/16(Tue) 19:54:40)
No73356 (ビール呑み さん) に返信

> >>web上のリソースを参考にvb.netプログラムの勉強をVS2010で始めたところでございます。
>>And ではなく AndAlso を…というのは些末な話として:
>
> ?????
> すみません、わからないので解説いただけると幸いです。
>

あ、「If m.Msg = WM_NCHITTEST And m.Result.ToInt32() = HTCLIENT Then」
のところのことでしょうか?
引用返信 編集キー/
■73358 / inTopicNo.5)  Re[4]: フォーム最大化のキャンセル方法
□投稿者/ Hongliang (233回)-(2014/09/16(Tue) 21:05:24)
FormBorderStyle.Noneの場合、MaximizeBoxおよびMinimizeBoxの設定は無視されますが、その結果WS_MAXIMIZEBOXフラグが立ったままになって最大化ができてしまう、ということのようですね。
// Win+↑でも最大化できるのでダブルクリックさせなくさせられれば良いというわけでもない。

CreateParamsをオーバーライドして、StyleからWS_MAXIMIZEBOX(&H10000)ビットを落としてやれば最大化できなくなります。
Const WS_MAXIMIZEBOX As Integer = &H10000
Dim p As CreateParams = MyBase.CreateParams
p.Style = p.Style And (Not WS_MAXIMIZEBOX)
Return p
引用返信 編集キー/
■73360 / inTopicNo.6)  Re[5]: フォーム最大化のキャンセル方法
□投稿者/ ビール呑み (6回)-(2014/09/17(Wed) 00:31:58)
No73358 (Hongliang さん) に返信


動きましたぁ!!!


もとい…


Hongliangさんにご指示いただいた記述を追加したところ、ダブルクリックしても
ピクリとも動きませんでしたぁ!!!

(動かないプログラムがこんなに嬉しいなんて…)

うーん、まだまだ知らない世界がいっぱいあるんですね。

後は、魔界の仮面弁士さんにご指摘いただいているように、
「ダブルクリックされた時の処理」を復活させてやる必要がありますね。
これについてはもうしばらく試行錯誤してみます。

魔界の仮面弁士さん、Hongliangさん、ありがとうございました。
またお世話になると思いますが、よろしくお願いいたします。
m(_ _)m

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -