変更前の解像度が取得されてしまう。

解決


DS  2010-09-03 00:58:53  No: 102545  IP: [192.*.*.*]

変更前の解像度が取得されてしまう。

(OS WINXP)

よろしくお願いいたします。

画面の解像度が変更された場合に、それに応じてウインドウの位置を変えるようにしたいと思いまして、
いろいろ検索して調べました。
その結果、プログラムをサブクラス化して「WM_DISPLAYCHANGE」というウインドウメッセージをフックすればいいということが分かったのですが、 
このメッセージは解像度が変化する直前に送られてくるようなのです。
なので取得できる解像度は、変化する前のものとなってしまいました。
どうすれば、変化した後の解像度を知ることができるでしょうか?

どうかよろしくお願いいたします。

(下は私が実行したプログラムを要約したものです。)

フォームにテキストボックスを一つ貼り付けて、
'****Form1****
Private Sub Form_Load()
    SubClass
End Sub

Private Sub Form_Unload(Cancel As Integer)
    UnSubClass
End Sub

Private Sub SubClass()
    m_wndprcNext = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub

Private Sub UnSubClass()
    SetWindowLong hwnd, GWL_WNDPROC, m_wndprcNext
End Sub


'****Module1****
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal wndrpcPrev As Long, ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Const GWL_WNDPROC = -4

Public m_wndprcNext As Long
Public Const WM_DISPLAYCHANGE = &H7E

Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

    Select Case uMsg
        Case WM_DISPLAYCHANGE
            TWidth% = Screen.Width \ Screen.TwipsPerPixelX
            THeight% = Screen.Height \ Screen.TwipsPerPixelY
            Form1.Text1.Text = CStr(TWidth%) & "*" & CStr(THeight%)
    End Select
    WindowProc = CallWindowProc _
     (m_wndprcNext, hwnd, uMsg, wParam, ByVal lParam)
End Function

編集 削除
魔界の仮面弁士  2010-09-03 09:16:37  No: 102546  IP: [192.*.*.*]

> 画面の解像度が変更された場合に、それに応じて
> ウインドウの位置を変えるようにしたいと思いまして、
その場合、作業領域(タスクバー部を除いたエリア)も求める必要があるかも。

たとえばこんなイメージで。

Private Sub SysInfo1_DisplayChanged() 
  If Screen.ActiveForm.Width > SysInfo1.WorkAreaWidth Then
    Screen.ActiveForm.Left = SysInfo1.WorkAreaLeft
    Screen.ActiveForm.Width = SysInfo1.WorkAreaWidth
  End If
  If Screen.ActiveForm.Height > SysInfo1.WorkAreaHeight Then
    Screen.ActiveForm.Top = SysInfo1.WorkAreaTop
    Screen.ActiveForm.Height = SysInfo1.WorkAreaHeight
  End If
End Sub


> どうすれば、変化した後の解像度を知ることができるでしょうか?
WM_DISPLAYCHANGE の場合、

wParam = 変更後の色数(bpp:ピクセルあたりのビット数)
lParam = 新しい解像度(上位16bit=高さ、下位16bit=幅)

のはずです。
http://msdn.microsoft.com/ja-jp/library/cc428309.aspx

編集 削除
DS  2010-09-03 20:57:13  No: 102547  IP: [192.*.*.*]

魔界の仮面弁士さん、ご回答ありがとうございます。
いつもお世話になりっぱなしで恐縮です。

> その場合、作業領域(タスクバー部を除いたエリア)も求める必要があるかも。
仰る通りでした。
SysInfoコントロールってこういうことに使えたのですね!!
まったく使ったことがありませんでした。
サブクラス化しなくてもできるなんて、本当に便利なコントロールを教えて下さってありがとうございます。

> wParam = 変更後の色数(bpp:ピクセルあたりのビット数)
> lParam = 新しい解像度(上位16bit=高さ、下位16bit=幅)
こちらの方法でも変更後の解像度を取得することが出来ました。

どうもありがとうございました。

編集 削除