複数フォームの同期移動

解決


ゆき  2006-09-07 20:46:06  No: 96544

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などで
なにかをやっているらしいのですが、私にはまったく知識がなく
理解、原因の追究ができません。

情報が少ないですが、なにか原因となりそうなこと等ありますでしょうか。
まったくの初心者でサンプルを元に実装しなければいけない為、困っています。

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


ガッ  2006-09-07 20:59:13  No: 96545

IDEのデバッガで追いかけれるのならそれが一番だけど、
とりあえずファイルなんかにログを採ってみるのが先決ではないかと。


ヤマ@文系  2006-09-08 07:21:28  No: 96546

こんにちは。
.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


ヤマ@文系  2006-09-08 07:22:13  No: 96547

timer1.enabled=Trueにしてください


ゆき  2006-09-11 14:02:48  No: 96548

回答が遅くなり申し訳ありません。
Timerを使用して行う方法は、以前にも試してみて、
どうしてもForm1と2の動作にタイムラグ?がでてしまい、
きれいに動かないで、飛ぶような感じになってしまいました。

ですので、先輩がサブクラス化のページを参照してみろということで
上記のソースになりました。


大吉末吉  2006-09-11 20:38:17  No: 96549

ゆき  さん  こんにちは。

> ですが、実際のプロジェクトに組み込むと上のフォームがフリーズして
> 見えなくなり、CPUの使用率も100%になってしまいフリーズしています。

状況的には、メッセージが無限発生しているような気がしますね。
単に、「組み込み方を間違った」のでは?

例えば、
Form1を移動したら、Form2を追従させて、
Form2を移動したら、Form1を追従させる
様にしていませんか?

そのため、
Form1を移動=>Form2を移動=>再度Form1を移動=>再度Form2を移動=>・・・
となってしまっているとか。

そうじゃなかったとしても、ガッ  さんが、おっしゃている様に、動作ログをとってみて、実際に、どういう動作をしているか確認する必要がありますよね。


ゆき  2006-09-12 11:46:51  No: 96550

大吉末吉へ
>例えば、
>Form1を移動したら、Form2を追従させて、
>Form2を移動したら、Form1を追従させる
>様にしていませんか?

確認しましたが、大丈夫だと思います。

みなさんがおっしゃるように、ログをとってもう一度
確認してみたいと思います。


ゆき  2006-09-12 12:07:58  No: 96551

皆様方、本当に申し訳ありません。

 WindowProc = CallWindowProc(oldWinProc, hWnd, uMsg, wParam, lParam)

が抜けていました;;

正常に動いたのですが、画面の動作がすごく重くなってしまいました。。。
あと、画面自体にコントロールとかが多いせいか、タイマーを使った場合と
あんまり変わらないような感じで、タイムラグが発生してちょっと下のフォームが飛んでしまうような感じになってしまいます。

そんなもんなのでしょうか?

一応、解決をつけておきますが、なにか意見等ありましたら
参考にしたいのでお願いします。

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


ゆき  2006-09-12 14:47:37  No: 96552

たびたびすいません。

上記のソースを記述するとデバックするときに
フリーズしてしまいます。

デバックの時はコメントをする以外に、方法はないのでしょうか?


我龍院忠太  2006-09-12 20:49:20  No: 96553

デバッグの時はタイマーで、コンパイル時にサブクラスにしたらいかがですか。


魔界の仮面弁士  2006-09-12 21:48:31  No: 96554

> なにか意見等ありましたら
Left / Top プロパティを使って移動するよりも、Move メソッドを使って
1 回の呼び出しで位置を変更した方が良いかも。

> デバックの時はコメントをする以外に、方法はないのでしょうか?
サブクラス化処理中もデバッグ可能にするための『DBGWPROC.DLL』という 
ActiveX DLL が存在します。

この DLL は、以前は Microsoft の Owner's Area というサイトから
ダウンロードできたのですが、今は Visual Studio Owner's Area の
ページ自体が、残念ながら閉鎖されてしまっています。

それでも、google 等で探せば、DLL の配布先と使い方が見つかりますので、
もし興味があれば、調べてみては如何でしょうか。


ゆき  2006-09-14 16:42:38  No: 96555

こんにちは

我龍院忠太さんへ
>デバッグの時はタイマーで、コンパイル時にサブクラスにしたらいかがですか。

私にも簡単にできるので、今はとりあえずそうしています。
ありがとうございました。

魔界の仮面弁士さんへ
>Left / Top プロパティを使って移動するよりも、Move メソッドを使って
>1 回の呼び出しで位置を変更した方が良いかも。

Call Form2.Move(Form1.Left, Form1.Top + Form1.Height)

ってことですね?
なるほど、一行でシンプルですね
ありがとうございます。

>サブクラス化処理中もデバッグ可能にするための『DBGWPROC.DLL』という 
>ActiveX DLL が存在します。

なんか、DLLと聞いただけで目眩がしてきそうですが、勉強の為に調べてみます><

いつも、ありがとうございます。


ヤマ@文系  2006-09-19 10:16:55  No: 96556

すいません、全くお役に立てなかったので何かしら
参考になるかわかりませんが書いておきます。

*******************************
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


ヤマ@文系  2006-09-19 10:18:18  No: 96557

busyflag=false
end if

ではなく
end if
busyflag=false

に訂正。。


ゆき  2006-09-21 21:39:15  No: 96558

ヤマ@文系さん こんにちは

遅くなってすいません。
動作していたので安心してしまいました^^;

さっそく試してみますね

ありがとうございます。


※作成する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。







   このエントリーをはてなブックマークに追加