2つのフォームを上下に並べて、上のフォームが移動したら下のフォームもそれに合わせて移動するというPGをどこかのサンプルを元に、サブクラスを利用して作成しました。
上のフォーム:Form1
下のフォーム:Form2
*******************************
Form1のソース
*******************************
Private Sub Form_Load()
Form2.Show
Call StartSubClass(Me.hWnd)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Call StopSubClass(Me.hWnd)
End Sub
*******************************
*******************************
標準モジュールのソース
*******************************
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" ( _
ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Const GWL_WNDPROC = (-4)
Public Const WM_MOVE = &H3
'元のウィンドウプロシージャのポインタ
Private oldWinProc As Long
'サブクラス化開始
Public Sub StartSubClass(hWnd As Long)
oldWinProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
'サブクラス化終了
Public Sub StopSubClass(hWnd As Long)
Dim rtn As Long
rtn = SetWindowLong(hWnd, GWL_WNDPROC, oldWinProc)
End Sub
'ウィンドウプロシージャ
Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = WM_MOVE Then
Form2.Top = Form1.Top + Form1.Height
Form2.Left = Form1.Left
Form1.Print Form1.Left & "," & Form1.Top
End If
WindowProc = CallWindowProc(oldWinProc, hWnd, uMsg, wParam, lParam)
End Function
*******************************
これだけのサンプルプロジェクトですと、期待したとおり、上のフォームの
移動に併せて下のフォームも移動させることができました。
ですが、実際のプロジェクトに組み込むと上のフォームがフリーズして
見えなくなり、CPUの使用率も100%になってしまいフリーズしています。
実際のプロジェクトでは他にもいろいろとSkyWorksProなどで
なにかをやっているらしいのですが、私にはまったく知識がなく
理解、原因の追究ができません。
情報が少ないですが、なにか原因となりそうなこと等ありますでしょうか。
まったくの初心者でサンプルを元に実装しなければいけない為、困っています。
どなたかよろしくお願いします。
IDEのデバッガで追いかけれるのならそれが一番だけど、
とりあえずファイルなんかにログを採ってみるのが先決ではないかと。
こんにちは。
.NETではないですね。これは。
そうすると、IDEのデバッガでやるとIDEがフリースしそうなきがするんですが。。ちがかったかな。仮面弁士様が詳しくログで書いてあるんで
それでデバッグできるとは思うんですが、どっかのソースを適当にもってきてよくわかっていない状況だと思うのでつらいとおもいます。
で、
これではだめですかね。。
timer1コントロールを追加しています。
Private Sub Form_Load()
timer1.interval=50'ミリ秒
Form2.Show vbModeless'モードレス form1,2両方操作可能ってことです。
End Sub
Private Sub Timer1_Timer()
Form2.Top = Form1.Top + Form1.Height
Form2.Left = Form1.Left
End Sub
timer1.enabled=Trueにしてください
回答が遅くなり申し訳ありません。
Timerを使用して行う方法は、以前にも試してみて、
どうしてもForm1と2の動作にタイムラグ?がでてしまい、
きれいに動かないで、飛ぶような感じになってしまいました。
ですので、先輩がサブクラス化のページを参照してみろということで
上記のソースになりました。
ゆき さん こんにちは。
> ですが、実際のプロジェクトに組み込むと上のフォームがフリーズして
> 見えなくなり、CPUの使用率も100%になってしまいフリーズしています。
状況的には、メッセージが無限発生しているような気がしますね。
単に、「組み込み方を間違った」のでは?
例えば、
Form1を移動したら、Form2を追従させて、
Form2を移動したら、Form1を追従させる
様にしていませんか?
そのため、
Form1を移動=>Form2を移動=>再度Form1を移動=>再度Form2を移動=>・・・
となってしまっているとか。
そうじゃなかったとしても、ガッ さんが、おっしゃている様に、動作ログをとってみて、実際に、どういう動作をしているか確認する必要がありますよね。
大吉末吉へ
>例えば、
>Form1を移動したら、Form2を追従させて、
>Form2を移動したら、Form1を追従させる
>様にしていませんか?
確認しましたが、大丈夫だと思います。
みなさんがおっしゃるように、ログをとってもう一度
確認してみたいと思います。
皆様方、本当に申し訳ありません。
WindowProc = CallWindowProc(oldWinProc, hWnd, uMsg, wParam, lParam)
が抜けていました;;
正常に動いたのですが、画面の動作がすごく重くなってしまいました。。。
あと、画面自体にコントロールとかが多いせいか、タイマーを使った場合と
あんまり変わらないような感じで、タイムラグが発生してちょっと下のフォームが飛んでしまうような感じになってしまいます。
そんなもんなのでしょうか?
一応、解決をつけておきますが、なにか意見等ありましたら
参考にしたいのでお願いします。
ありがとうございました。
たびたびすいません。
上記のソースを記述するとデバックするときに
フリーズしてしまいます。
デバックの時はコメントをする以外に、方法はないのでしょうか?
デバッグの時はタイマーで、コンパイル時にサブクラスにしたらいかがですか。
> なにか意見等ありましたら
Left / Top プロパティを使って移動するよりも、Move メソッドを使って
1 回の呼び出しで位置を変更した方が良いかも。
> デバックの時はコメントをする以外に、方法はないのでしょうか?
サブクラス化処理中もデバッグ可能にするための『DBGWPROC.DLL』という
ActiveX DLL が存在します。
この DLL は、以前は Microsoft の Owner's Area というサイトから
ダウンロードできたのですが、今は Visual Studio Owner's Area の
ページ自体が、残念ながら閉鎖されてしまっています。
それでも、google 等で探せば、DLL の配布先と使い方が見つかりますので、
もし興味があれば、調べてみては如何でしょうか。
こんにちは
我龍院忠太さんへ
>デバッグの時はタイマーで、コンパイル時にサブクラスにしたらいかがですか。
私にも簡単にできるので、今はとりあえずそうしています。
ありがとうございました。
魔界の仮面弁士さんへ
>Left / Top プロパティを使って移動するよりも、Move メソッドを使って
>1 回の呼び出しで位置を変更した方が良いかも。
Call Form2.Move(Form1.Left, Form1.Top + Form1.Height)
ってことですね?
なるほど、一行でシンプルですね
ありがとうございます。
>サブクラス化処理中もデバッグ可能にするための『DBGWPROC.DLL』という
>ActiveX DLL が存在します。
なんか、DLLと聞いただけで目眩がしてきそうですが、勉強の為に調べてみます><
いつも、ありがとうございます。
すいません、全くお役に立てなかったので何かしら
参考になるかわかりませんが書いておきます。
*******************************
Form1のソース
*******************************
Private Sub Form_Load()
me.show'<--サブクラス化の前に書いておく。
Form2.Show
Call StartSubClass(Me.hWnd)
End Sub
'ウィンドウプロシージャ
Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
static busyflag as boolean
'処理中はメッセージを飛ばす・・のはどうでしょうか。。?
if busyflag=false then
busyflag=true
If uMsg = WM_MOVE Then
Call Form2.Move(Form1.Left, Form1.Top + Form1.Height)
busyflag=false
end if
End If
WindowProc = CallWindowProc(oldWinProc, hWnd, uMsg, wParam, lParam)
End Function
busyflag=false
end if
ではなく
end if
busyflag=false
に訂正。。
ヤマ@文系さん こんにちは
遅くなってすいません。
動作していたので安心してしまいました^^;
さっそく試してみますね
ありがとうございます。
| ツイート |
|