質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

Visual Studio 2013

Microsoft Visual Studio 2013は、Microsoftによる統合開発環境(IDE)であり、多種多様なプログラミング言語に対応しています。 Visual Studio 2012の次のバージョンです

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

1回答

7987閲覧

VBでTCM_SETCURSELのSendMessage処理と、その後のBM_CLICK操作が正常に動作しない

ot2os

総合スコア23

VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

Visual Studio 2013

Microsoft Visual Studio 2013は、Microsoftによる統合開発環境(IDE)であり、多種多様なプログラミング言語に対応しています。 Visual Studio 2012の次のバージョンです

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

1クリップ

投稿2017/08/01 05:08

自動でプリンターの[印刷設定]を呼び出し、[ノズルチェックパターン印刷]を実施するプログラムをVBで制作したいと思います。
途中、SendMessageでTCM_SETCURSELを投げた際、「印刷設定」ダイアログ内の選択タブは切り替わりますが、タブ内の描画が切り替わりません。(下記コード●02部分)
下記スクリーンショットの通り、「ユーティリティ」タブが選ばれていますが、表示されいる中身は「基本設定」タブのものになっています。
イメージ説明
ちなみに、このまま続けて手動で別タブに切り替えると、タブ内の表示が空白状態になり、画面下部の[OK]や[キャンセル]のボタンが残ります。

また、該当コードの●02部分をコメントアウトし、一旦処理を止めてから手動でタブを切り替え、その後の●03部分を実行しても「ノズルチェックパターン印刷」のウィンドウが出てきません。
●02、●03を両方コメントアウトし、手動で「ノズルチェックパターン印刷」ウィンドウを出すと、その後の処理は●04~●07まですべて正常に動きます。

そのため、タブを含むウィンドウの操作が何かうまくいっていない気がしますが、原因と対処法がわかりません。

lang

1Public Class Form1 2 3 'FindWindow関数(Unicode実行) 4 Declare Unicode Function FindWindow Lib "user32.dll" Alias "FindWindowW" _ 5 (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer 6 '<DllImport("user32.dll", CharSet:=CharSet.Unicode)> 7 'Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer 8 'End Function 9 10 Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _ 11 (ByVal hwndParent As Integer, ByVal hwndChildAfter As Integer, _ 12 ByVal lpszClass As String, ByVal lpszWindow As String) As Integer 13 14 15 'SendMessage用 16 Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _ 17 (ByVal hWnd As Integer, ByVal MSG As Integer, _ 18 ByVal wParam As Integer, ByVal lParam As Integer) As Integer 19 20 'PostMessage用 21 Declare Function PostMessage Lib "user32" Alias "PostMessageA" _ 22 (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long 23 24 Public Const BM_CLICK = &HF5 25 Public Const TCM_SETCURSEL = &H130C 26 Public Const TCM_GETITEMCOUNT = &H1304 27 28 29 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 30 Dim Printer_Name As String = "【ダミー】Canon Inkjet MP630 series" 31 32 'Processオブジェクトを作成 33 Dim p As New System.Diagnostics.Process() 34 35 36 'ComSpec(cmd.exe)のパスを取得して、FileNameプロパティに指定 37 p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec") 38 39 'ウィンドウを表示しないようにする 40 p.StartInfo.CreateNoWindow = True 41 'コマンドラインを指定("/c"は実行後閉じるために必要) 42 p.StartInfo.Arguments = "/c start rundll32 printui.dll, PrintUIEntry /e /n """ & Printer_Name & """" 43 44 '●01起動 45 p.Start() 46 47 'プロセス終了まで待機する 48 'WaitForExitはReadToEndの後である必要がある 49 '(親プロセス、子プロセスでブロック防止のため) 50 p.WaitForExit() 51 p.Close() 52 53 54 'Text: 【ダミー】Canon Inkjet MP630 series 印刷設定 55 Dim hwnd1 As Integer, hwnd2 As Integer 56 Dim Result As String 57 58 '印刷設定ウィンドウのIDとタブバーのIDを取得 59 hwnd1 = FW("#32770", Printer_Name & " 印刷設定") 60 hwnd2 = FWex(hwnd1, 0, "SysTabControl32", "") 61 62 63 'タブ数カウント 64 Debug.Print("タブ数:" & SendMessage(hwnd2, TCM_GETITEMCOUNT, 0, 0)) 65 66 '●02「ユーティリティ」タブへの切り替え 67 Result = SendMessage(hwnd2, TCM_SETCURSEL, 3, 0) 68 Debug.Print("タブ切り替え前:" & Result) 69 70 71 '●03「ノズルチェックパターン印刷」ボタンクリック 72 hwnd2 = FWex(hwnd1, 0, "Button", "ノズルチェックパターン印刷") 73 'hwnd3 = FWex(hwnd1, 0, "Button", "ノズルチェックパターン印刷") 74 SendMessage(hwnd2, BM_CLICK, 1, 0) 75 76 77 '●04「ノズルチェックパターン印刷」ウィンドウで「カセット」をクリック 78 hwnd1 = FW("#32770", "ノズルチェックパターン印刷") 79 hwnd2 = FWex(hwnd1, 0, "Button", "カセット(&C)") 80 SendMessage(hwnd2, BM_CLICK, 1, 0) 81 '●05「確認パターン印刷」をクリック 82 hwnd2 = FWex(hwnd1, 0, "Button", "確認パターン印刷(&P)") 83 SendMessage(hwnd2, BM_CLICK, 1, 0) 84 85 '●06印刷完了後、「パターンの確認」ウィンドウの「終了」ボタンをクリック 86 hwnd1 = FW("#32770", "パターンの確認") 87 hwnd2 = FWex(hwnd1, 0, "Button", "終了(&X)") 88 SendMessage(hwnd2, BM_CLICK, 1, 0) 89 90 '●07最後に「OK」ボタンクリックですべて終了 91 hwnd1 = FW("#32770", Printer_Name & " 印刷設定") 92 hwnd2 = FWex(hwnd1, 0, "Button", "OK") 93 SendMessage(hwnd2, BM_CLICK, 1, 0) 94 95 End Sub 96 97 Private Function FW(ByVal Class_Name As String, ByVal Window_Name As String) 98 Dim hwnd As Integer = 0 99 Do Until hwnd > 0 100 'Debug.Print("Window_Name:" & Window_Name) 101 hwnd = FindWindow(Class_Name, Window_Name) 102 System.Threading.Thread.Sleep(200) '念のため0.2秒停止 103 My.Application.DoEvents() '描画フリーズ防止 104 Loop 105 FW = hwnd 106 Debug.Print(Window_Name & ":" & hwnd) 107 End Function 108 109 Private Function FWex(ByVal hwnd1 As Integer, ByVal Arg As Integer, ByVal Class_Name As String, ByVal Obj_Name As String) 110 Dim hwnd2 As Integer = 0 111 Do Until hwnd2 > 0 112 hwnd2 = FindWindowEx(hwnd1, 0, Class_Name, Obj_Name) 113 System.Threading.Thread.Sleep(200) '念のため0.2秒停止 114 My.Application.DoEvents() '描画フリーズ防止 115 Loop 116 FWex = hwnd2 117 Debug.Print(Obj_Name & "、" & Class_Name & ":" & hwnd2) 118 End Function 119 120End Class

Immediate Windowの結果は下記のとおりです。

Immediate

1【ダミー】Canon Inkjet MP630 series 印刷設定:853970 2、SysTabControl32:591850 3タブ数:4 4タブ切り替え前:0

下記資料を見る限り、TCM_SETCURSELの戻り値が0なので、上記の結果を見るとここまでは正常に進んでいるはずなのかなと思っております。
https://msdn.microsoft.com/ja-jp/library/windows/desktop/bb760612(v=vs.85).aspx

タブ切り替えを正常に成功させる方法と、その後のタブ内の「ノズルチェックパターン印刷」ボタンの操作を成功させる方法をお願いいたします。

開発環境:
OS:Windows10x86 1703
Visual Studio 2013

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

同じような事をVBAでやろうとしていました。
Result = SendMessage(hwnd2, TCM_SETCURSEL, 3, 0)

Private Const TCM_FIRST As Int32 = &H1300
Private Const TCM_SETCURFOCUS As UInt32 = (TCM_FIRST + 48)
Result = SendMessage(hwnd2, TCM_SETCURFOCUS, 3, 0)
でいかがでしょうか?

TCM_SETCURSELのリファレンスに以下の記載があるので、更新通知が飛んでないのが原因ではないでしょうか?
A tab control does not send a TCN_SELCHANGING or TCN_SELCHANGE notification code when a tab is selected using this message.

投稿2017/08/07 05:55

ryoooooo

総合スコア51

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ot2os

2017/08/10 08:32

ありがとうございます! ご教示いただいた内容で正確にタブの切り替え、内容の表示ができました! 一度TCM_SETCURSELで更新通知が飛ばないままタブを変えてしまうと、後から手動でタブ変更しても描画が崩れたままになるようですね。 そして、その後の●03「ノズルチェックパターン印刷」のクリックも動作しないままなので、ひょっとするとこちら別原因かもしれません。 わかり次第追加でご報告いたします。
ot2os

2017/08/17 09:05

BM_CLICKのアドバイスありがとうございます。 ●03に関して、ご指摘通り、hwnd2が取得できていないため、先に進めていない状態です。 ちなみに、Spy++で見た結果、それぞれの親子関係は「デスクトップ」直下から、下記のように表示されています。 「`【ダミー】Canon Inkjet MP630 series 印刷設定`#32770 (ダイアログ)」  └「`ユーティリティ`#32770 (ダイアログ)」   └「`ノズルチェックパターン印刷`Button」 InputBoxコマンドにて「ノズルチェックパターン印刷」のウィンドウハンドル(Spy++で調査)をhwnd2に代入すれば「ノズルチェックパターン印刷」のボタンクリックまでは動作したので、やはりウィンドウハンドルが正常に取得できていないのが問題の様子です。 ただし、これを行うと、なぜかその後の●04以降でウィンドウハンドルが取得できず先に進めなくなります。 手作業で「ノズルチェックパターン印刷」ボタンを押下した場合は、●04以降からすべて正常に動作します。 ちなみに、「ノズルチェックパターン印刷」ダイアログウィンドウは、Spy++で見た結果は「デスクトップ」直下に存在します。 「`ノズルチェックパターン印刷`#32770 (ダイアログ)」
ryoooooo

2017/08/17 12:57

Syp++の階層から '●03「ノズルチェックパターン印刷」ボタンクリック hwnd1_1 = FWex( hwnd1, 0, "#32770", "ユーティリティ" ) hwnd2 = FWex( hwnd1_1, 0, "Button", "ノズルチェックパターン印刷" ) PostMessage( hwnd2, BM_CLICK, 0, 0 ) でいかがでしょうか。 後、ボタン押した後に次のウィンドウ(保存ダイヤログなど)が開く場合はPostmessageで押さないと応答待ちにで固まる事が多いです。(上部の定義はSendmessageと同じくLongじゃなくIntegerでいいと思います) Declare Function PostMessage Lib "user32" Alias "PostMessageA" _ (ByVal hWnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer ByVal lParam As Integer) As Integer
ot2os

2017/08/18 07:15

ありがとうございます! FWexにて「ユーティリティ」タブから順に取得したところ、正常に動作しました。 また、おっしゃる通り、PostMessageにて改善したところ、●04以降の動作もすべて問題なく動作しました。応答待ちで固まっていただけだったんですね。 重ねてお礼申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問