初めてのソースコードでのAPI使用についての疑問

このQ&Aのポイント
  • 初めてAPIを使用してプログラミングしている際、クラス化やウィンドウハンドルについて理解できていない状況です。
  • このソースコードを改善することは可能か疑問です。
  • "AppActivate Label4.Caption"のような書き方が必要な理由や、より効果的な書き方について教えて欲しいです。
回答を見る
  • ベストアンサー

このソース

APIなるものを初めて使ってプログラミングしているのですが、クラス化とか ウィンドウハンドルとか意味わからないです。 というわけでこのソースをきれいにできますか? (簡略してます。疑問は下の方にあります。) Private Sub XXX() Dim lngWindowHandleForeground As Long Dim strWindowText As String   Dim lngResult As Long ' アクティブなウィンドウのハンドルを取得 lngWindowHandleForeground = _ GetForegroundWindow() ' アクティブなウィンドウのタイトルを取得 lngResult = _ GetWindowText( _ lngWindowHandleForeground, _ strWindowText, _ Len(strWindowText)) ' アクティブなウィンドウのタイトルを表示 Label4.Caption = _    '※→納得いかないところ Left(strWindowText, _ InStr(strWindowText, _ vbNullChar) - 1) End Sub ウィンドウのタイトルを取得し別のサブルーチンで こんな書き方をしています。 AppActivate Label4.Caption つまりいちいちLabel4(しょうがないので作ったラベルです(^^ゞ)というラベルを仲介しないと引数が足りませんとエラーが出てしまいます。 理想としては AppActivate strWindowText もしくは   AppActivate lngResult  とできないんでしょうか? なぜこういう書き方ができないか教えてもらえると助かります。 賢い書き方があったら教えてください。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

試していないので、うまくいくかわからないですけど・・・ Label4.Caption = ActiveTitle = :'Dim ActiveTitle As Stringをプログラムの外で宣言 として sub command1_Click() AppActivate ActiveTitle end sub とすれば、よいのではないでしょうか? また、 Sub XXX() を Function XXX() に変更して Label4.caption = を XXX = に変更しアクティブなウィンドウのタイトルを取得したいところで ActiveTitle = XXX 'ActiveTitle は 上記と同様 としてもいいと思います。 Label4.Caption = _    '※→納得いかないところ Left(strWindowText, _ InStr(strWindowText, _ vbNullChar) - 1) の文の意味がわからない? ということではないですよね? APIの資料を見ていないので違うかもしれませんが、 lngResultはタスクIDではなかったような気がします。 >lngResult = GetWindowText( lngWindowHandleForeground, strWindowText,Len(strWindowText)) ??私の勘違いかもしれませんが、Len(strWindowText)の部分は、格納する変数の長さではなかったでしたっけ? これだと 0ですよね? Dim strWindowText As String * 256 とかになってるのでしょうか?   strWindowTextにタイトルを格納し、残りの部分(タイトル名の終わりのみ?)にNullが入るので Label4.Caption = Left(strWindowText, InStr(strWindowText, vbNullChar) - 1) でNullを取り除いているような気がするのですが・・・ 間違っていたらすみません。 他の方の回答がなく、私の憶測が間違っているようなら、また回答します。 質問の意味が違うようなら補足してください。

Scotty_99
質問者

お礼

回答ありがとうございました。 まだ自宅ではないので試せていないのですが、上記の方法試してご報告します。 >Dim strWindowText As String * 256 とかになってるのでしょうか?   でした(^^ゞ。必要ないと思って* 256 はとってしまったのです。 よくわかりましたね。私はAPIが全然わからなくて、資料も300の技しかないですし。またよろしくお願いします。

Scotty_99
質問者

補足

言われたとおりの方法でできました! またよろしくお願いします。

その他の回答 (1)

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.2

Label4.Caption = _    '※→納得いかないところ Left(strWindowText, _ InStr(strWindowText, _ vbNullChar) - 1) ですが、VBはstring型(LPCSTR型)で文字列を宣言しますが C言語では配列でとります。 例えば char str[100]; (vbだと dim str as string*100みたいな感じ) とすると半角100文字分の文字列のスペースが確保できます。 vbのstring型では最初に何文字分データがあるという情報がはいっていますが Cのchar型にははいっていません。そこで終端文字というのが あり、その文字が来ればその文字列は終了という意味になります。 その終端文字というのがvbNullCharにあたります。 strWindowText が "abcdefg(終端文字)hijklmn"だった場合 Left(strWindowText, InStr(strWindowText, vbNullChar) - 1) とすると strWindowText が "abcdefg"となるのです。 #あとクラス化ではなくサブクラス化では?

Scotty_99
質問者

お礼

すみません。ちょっと私にはむずかしいです。多分、strWindowText が配列か どうかでしょうか?私が勝手に削除し(^^ゞ、文字型にしてしまいましたm(__)m。 回答ありがとうございました。

関連するQ&A

  • VB BitBlt他でのエラー

    ネットを見ながらVisual Basicを触り始めたのですが、下記のようなコードを実行すると「スタックを不安定にしています」といった感じのエラーが出てしまいます。 多分基本的な見落としだとは思うのですが、調べても上手い解決策が見つからず、質問させて頂いた次第です。  どうか、皆様のお知恵をお貸しください。 ・環境 Windows7 64bit - Microsoft Visual studio2017 - Visual Basic - Windowsデスクトップ - Windowsフォームアプリケーション ・やりたい事 別ソフトのウィンドウのタイトル、座標、画像を取得したい。 ・エラー 下記コードを開始(上の緑の三角)して実行すると、(1)のGetForegroundWindowは問題ないのですが、(2)のGetClientRect、(3)のGetWindowText、(4)のBitBltの部分を実行する際に、次のようなエラーが出てしまいます(3か所とも、関数名以外は同じエラーです)。 マネージド デバッグ アシスタント 'PInvokeStackImbalance' Message=マネージド デバッグ アシスタント 'PInvokeStackImbalance' : 'PInvoke 関数 'WindowsApp1!WindowsApp1.Form1::BitBlt' がスタックを不安定にしています。PInvoke シグネチャがアンマネージ ターゲット シグネチャに一致していないことが原因として考えられます。呼び出し規約、および PInvoke シグネチャのパラメーターがターゲットのアンマネージ シグネチャに一致していることを確認してください。' ・コード Imports OpenCvSharp Public Class Form1 Declare Function GetForegroundWindow Lib "user32" () As Long Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As Rect) As Long Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long Declare Function BitBlt Lib "gdi32" Alias "BitBlt" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long Public Const SRCCOPY = &HCC0020 'S Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click System.Threading.Thread.Sleep(1000) '指定ミリ秒待機する Dim hWnd As IntPtr = GetForegroundWindow() '(1)選択ウィンドウのハンドルを取得 'Dim winRect As New Rect 'GetClientRect(hWnd, winRect) '(2)ウィンドウ座標取得 Dim Title As String = Space(255) Dim ret As Long = GetWindowText(hWnd, Title, Len(Title)) '(3)ウィンドウのタイトルを取得 Title = Microsoft.VisualBasic.Left(ret, InStr(ret, vbNullChar) - 1) Dim img As IntPtr BitBlt(img, 0, 0, 100, 100, hWnd, 0, 0, SRCCOPY) '(4)ウィンドウの画像を取得 End Sub End Class

  • GetWindowTextでアドレスバーからURLを取得したい

    VB6.0でGetWindowTextを使用し、ブラウザ(IE)のアドレスバー部に 表示されているURLを取得したいと考えています。 ウィンドウハンドルを取得してキャプションを得るということに なると思うのですが、下記の内容においてGetWindowTextLengthの 戻り値がどうしても0になってしまいます。 URLはキャプションとして取得できないのでしょうか。 同じ方法でブラウザのタイトルバーの文字列を取得できることは 確認できています。 おわかりになられる方いらっしゃいましたら、よろしくお願い致します。 Private Sub Command3_Click() Dim hwnd As Long Dim Rc As Long Dim Str As String Dim Bite As Long hwnd = "&H" & アドレスバー部のウィンドウハンドル 'Rc = キャプションのバイト数 Rc = GetWindowTextLength(hwnd) MsgBox Rc 'エラーチェック If Rc = 0 Then Exit Sub 'キャプションのバイト数分のバッファ確保 Str = String(Rc, vbNullChar) 'Bite = キャプションのバイト数 'Str = キャプション文字 Bite = GetWindowText(hwnd, Str, Rc) 'Text1.Text = Str の左端の文字からキャプションのバイト数分 Text1.Text = Left(Str, Bite) End Sub

  • GetWindowText、GetActiveWindowについて

    こんばんは。よろしくお願いします。 まずは以下をご覧ください。 Excel VBA です。 Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Sub Sample() Dim rtn, rtn2 As Long Dim Name As String Dim Leng As Long Dim ReturnValue ReturnValue = Shell("CALC.EXE", 1) AppActivate ReturnValue Sleep 500 Name = String(250, Chr(0)) Leng = Len(Name) rtn = GetActiveWindow() rtn2 = GetWindowText(rtn, Name, Leng) Debug.Print Name End Sub これを実行しても、イミディエイトウインドウに「電卓」は出ません。 エラーもありません。 なぜなのでしょうか?

  • VB2010 ウィンドウタイトルを取得

    こんにちはVB学習を始めて2週間になりました。 Webの記事などを参考にしていますがバージョンによって記述が変わって苦戦しています。 今回ご質問したい内容です。 ボタンを押すとメモ帳が起動されているか調べてそのウィンドウタイトルを得る ウィンドウタイトルで検索してハンドルを取得してそのままそのハンドルで逆に ウィンドウタイトルを得ています(無意味な処理ですが学習用という事で) Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hWnd As Integer, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim ECHandle As Integer Dim Titlename As String Titlename = vbNullString ECHandle = FindWindow(vbNullString, "無題 - メモ帳") GetWindowText(ECHandle, Titlename, 255) Label5.Text = Titlename If ECHandle = 0 Then Label4.Text = "取得できない" Else Label4.Text = "取得出来た" & ECHandle & Titlename End If End Sub 結果はというと Titlename が空っぽのままでタイトルが取得できません どのような原因が考えられますでしょうか? よろしくお願いいたします。

  • VBAでアクティブなIEを操作

    現在VBAでIEを操作しようとしております。 URLやタイトルから指定してIEを操作することはできるようになりました。 今度はデスクトップの最善面にあるIEを操作したいと考えています。 下記を参考にして考えていますが、Hwndプロパティが読み取り専用らしく ハンドルから操作するIEを指定することができません。 http://okwave.jp/qa/q2147057.html そもそもVBAで可能なのかについても よく分からないのですが、恐れ入りますが代案を含め方法があれば教えてください。 ひとまず、煮詰まっていますが、 今残っているコードを載せておきます。 Public Declare Function GetForegroundWindow Lib "user32" () As Long ’--------------- Sub shell_test() Dim objie As Object Dim a as long Set obj = CreateObject("shell.application") a = GetForegroundWindow Debug.Print a End Sub

  • マウスのある個所の色

    お世話になります よろしくお願いします Pictureboxをクリックされたときに そのPictureboxがクリックされた箇所の色を16進数で取得したいのですが うまくいきません どこが間違っているのか教えてもらえないでしょうか? ソースは Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long Private Type POINTAPI x As Long y As Long End Type Private Sub Picture1_Click() Dim Poi As POINTAPI Dim iro As Long GetCursorPos Poi iro = GetPixel(Me.Picture1.hdc, Poi.x, Poi.y) Me.Label2.Caption = Poi.x Me.Label3.Caption = Poi.y Me.Label1.Caption = iro CloseHandle (Me.Picture1.hdc) End Sub GetPixcelの引数に-1しか入りません あと、もし数値で取れたとして それを16進数にする方法を教えてください よろしくお願いします

  • excel 2003 マクロですっきりさせたい

    お世話になります。 ユーザーフォーム上の テキストボックス 商品名_1の値が空白になったら ラベルも空白にするというマクロを組みました。 ラベルがたくさんあり、何かすっきりとできる方法があれば 教えてください!>< よろしくお願いします。 Private Sub 商品名_1_Change() If 商品名_1.Value = "" Then Label1_1.Caption = "" Label1_2.Caption = "" Label1_3.Caption = "" Label1_4.Caption = "" Label1_5.Caption = "" Label1_6.Caption = "" Label1_7.Caption = "" End If End Sub

  • アクティブウインドウのIMEコンテキスト取得を取得したい。

    アクティブウインドウのIMEコンテキスト取得を取得したい。 以下、問題のコードです。 ---ここから 'アクティブウインドウのハンドルを取得API宣言 Private Declare Function GetActiveWindow Lib "user32" () As Long 'IMEコンテキスト取得API宣言 Private Declare Function ImmGetContext Lib "imm32.dll" _ (ByVal hWnd As Long) As Long Private Sub CommandButton1_Click() 'アクティブウインドウのハンドルを取得 Dim hWnd As Long hWnd = GetActiveWindow() 'IMEコンテキスト取得 Dim himc As Long himc = ImmGetContext(hWnd) End Sub ---ここまで 上記のコードでアクティブウインドウ(上記例の場合、エクセル)でのIMEコンテキスト取得 したいと思っています。 hWndでは、ハンドルを取得できているのですが、 himcの戻り値が0になってしまって、IMEコンテキスト取得が失敗しています。 目的は、アクティブウインドウでのIMEの入力をローマジ入力の半角英数のみにすることです。 そのため、IMEコンテキスト取得を取得したいのですが、上記方法のどこがいけないでしょうか? どうぞよろしくお願いします。 言語:VBA(Excel 2007) OS:Vista

  • 「○秒」のところの表示を消したい

    ●質問内容 下記のコードを用いてユーザーフォーム上で ストップウォッチに時間を計測できるフォームを 作成しました。 添付の画像において計測時間は「0:02:29」となっていますが、 これを「0:02」としたいと考えています。 コードをどのように書き換えればよいでしょうか? ちなみに「○秒」のところは全て切り捨てにするつもりです。 ご存知の方ご教示願います。 ●コード Option Explicit Dim inProcess As Boolean ' True なら計測中を表す Private m_Kaishi As Date Private m_Syuryo As Date '開始時間をクリックするとラベル22が時間に変わる Private Sub CommandButton6_Click() Select Case inProcess Case False ' 計測を開始する inProcess = True m_Kaishi = Time Label22.Caption = FormatDateTime(m_Kaishi, vbShortTime) Label23.Caption = "" Label24.Caption = "" CommandButton6.Caption = "作業終了" Case True ' 計測を終了してインターバルを表示 inProcess = False m_Syuryo = Time Label23.Caption = FormatDateTime(m_Syuryo, vbShortTime) Label24.Caption = CDate(m_Syuryo - m_Kaishi) CommandButton6.Caption = "作業開始" End Select End Sub Private Sub UserForm_Initialize() CommandButton6.Caption = "作業開始" Label22.Caption = "" Label23.Caption = "" Label24.Caption = "" End Sub

  • 文字列連結演算子を使った繰り返し(ループ)について

    Text1・Command1・Label1 と並んだBoxでText1に数字を入力しCommand1を押すと漢数字(一,二…)となるプログラムなのですが、一桁ずつ求めて行き最後に文字列連結演算子を使って求める場合はどのようにしたらよいのでしょうか? エラーが出るのでどこかが変なんだと思うのですが、何度みてもわからなくて。。。今途中の段階ですが当方がやったところまでを乗せておきますので。違うところや付け足すところなど指摘したり教えていただけたらと思っています。よろしくお願いします。 Private Sub Command2_Click() Dim a As Integer Dim b As String a = Val(Text1.Text) For x = 1 To 5 If a = 1 Then Label1.Caption = "一" ElseIf a = 2 Then Label1.Caption = "二" ElseIf a = 3 Then Label1.Caption = "三" ElseIf a = 4 Then Label1.Caption = "四" ElseIf a = 5 Then Label1.Caption = "五" ElseIf a = 6 Then Label1.Caption = "六" ElseIf a = 7 Then Label1.Caption = "七" ElseIf a = 8 Then Label1.Caption = "八" ElseIf a = 9 Then Label1.Caption = "九" Else Label1.Caption = "〇" sText1 = "1" & "2" & "3" & "4" & "5" & "6" & "7" & "8" & "9" sLabel1 = "一" & "二" & "三" & "四" & "五" & "六" & "七" & "八" & "九" End If End Sub