今、タイトルバーのないアプリを作っているのですが、このアプリのウインドウを別アプリから、APIのFindWindow関数で見つけたいのですが、タイトルがないのでクラス名でしか見つけれません。同じクラスのウインドウが他にもあった場合、区別が付かず困っています。
具体的に申しますと、作ったアプリに二重起動防止機能を付けたい(すでに起動されている場合はそのアプリのウインドウを元の大きさに戻してアクティブにする)のですが、そのアプリにはタイトルバーがなく、FindWindowでは見つけれない場合があります。
このような場合どうすればいいでしょうか?
よろしくお願い致します。
No.6ベストアンサー
- 回答日時:
VB6.0で2重起動のチェック&2重起動時に起動中のウィンドウを
手前に持ってくるサンプルです。
Sub Main()
Dim lngReturnValue As Long
Dim strMyTitle As String
Dim lngPrevHwnd As Long
Dim lngTopHwnd As Long
Dim lngThreadID1 As Long
Dim lngThreadID2 As Long
' 2重起動の場合は、手前に持ってきて自分自身は終了する
strMyTitle = App.Title
App.Title = "$" & App.Title
lngPrevHwnd = FindWindow("ThunderRT6Main", strMyTitle)
If lngPrevHwnd <> 0 Then
lngTopHwnd = GetLastActivePopup(lngPrevHwnd)
If IsIconic(lngTopHwnd) = WIN32API_TRUE Then
lngReturnValue = ShowWindow(lngTopHwnd, SW_NORMAL)
End If
lngThreadID1 = GetWindowThreadProcessId(GetForegroundWindow(), ByVal 0&)
lngThreadID2 = GetCurrentThreadId()
lngReturnValue = AttachThreadInput(lngThreadID2, lngThreadID1, 1)
lngReturnValue = SetForegroundWindow(lngTopHwnd)
lngReturnValue = AttachThreadInput(lngThreadID2, lngThreadID1, 0)
Exit Sub
End If
App.Title = strMyTitle
Form1.Show
End Sub
APIの定義です。
Public Const WIN32API_TRUE As Long = 1
Public Const WIN32API_FALSE As Long = 0
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Public Declare Function GetLastActivePopup Lib "user32" _
(ByVal hwndOwnder As Long) As Long
Public Declare Function IsIconic Lib "user32" _
(ByVal hwnd As Long) As Long
Public Declare Function ShowWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long
Public Const SW_NORMAL = 1
Public Const SW_MAXIMIZE = 3
Public Const SW_MINIMIZE = 6
Public Declare Function GetForegroundWindow Lib "user32" () As Long
Public Declare Function SetForegroundWindow Lib "user32" _
(ByVal hwnd As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" _
(ByVal hwnd As Long, _
lpdwProcessId As Long) As Long
Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare Function AttachThreadInput Lib "user32" _
(ByVal idAttach As Long, _
ByVal idAttachTo As Long, _
ByVal fAttach As Long) As Long
VB5.0の場合は、ThunderRT6Main が ThunderRT5Main だと思います。
これは、VBのEXEで実行時にクラス名が ThunderRT6Main で
キャプションがプロジェクトのプロパティの実行ファイルの作成タブの
アプリケーションのタイトル(=App.Title=タスクマネージャのタスク
に表示されるタスク名)のウィンドウが必ず存在するので
このウィンドウをチェックしています。(このウィンドウは、サイズが
0なので見えません。)
また、開発環境(IDE)で動かすとこのウィンドウは存在しないので
EXEファイルにして実行して確認してください。
うぉ~~、 すごい~!!
ありがとうございます。
ThunderRT5Mainに書き換えたら動きました。
> これは、VBのEXEで実行時にクラス名が ThunderRT6Main で
> キャプションがプロジェクトのプロパティの実行ファイルの作成タブの
> アプリケーションのタイトル(=App.Title=タスクマネージャのタスク
> に表示されるタスク名)のウィンドウが必ず存在するので
そのようなウインドウが存在するとは知りませんでした!!
App.Titleを実行中に変更できるなんて思いもしませんでした。
おかげさまでシンプルなコードになりました。
どうもありがとうございました。
尚、ここで解決とさせて頂きます。
いろいろとごご教授くださった皆様、
どうもありがとうございました。
No.5
- 回答日時:
フォームの外枠を可変にしたいのでしょうか?
そうなると ControlBoxとCaptionで操作することになりますね
固定でよいのなら BorderStyleを 0の無しに設定してみてはいかがでしょう
これなら Captionは設定してあっても タイトルバーは表示されませんよ
どうもありがとうございます。
> BorderStyleを 0の無しに設定してみてはいかがでしょう
そうすると今度はタスクバーにも表示されなくなってしまうので・・・;;
noocyteさんが教えてくださったMutexを使ったやり方はむずかしかったので、ダミーのコマンドボタンを貼り付けるやり方で実現しました。
いろいろとありがとうございました。
No.4
- 回答日時:
>>SendMessageでCaptionを取得してみましょう
>タイトルバーがないのでCaptionもなく・・・;;
タイトルバーがなくても 作成したアプリケーションのフォームのCaptionプロパティが設定されているのであれば
WM_GETTEXTで取得できる場合がありますよ
先の投稿も一応検証してから アップしております VB6ですけどね ...
何度も、ありがとうございます。
> タイトルバーがなくても 作成したアプリケーションのフォームのCaptionプロパティが設定されているのであればWM_GETTEXTで取得できる場合がありますよ
VB5でフォームのCaptionプロパティを設定するとタイトルバーがなくならないです。(私のやり方が悪いのかも。)
フォームのControlBox プロパティを False にして、Caption プロパティを ""(プロパティウインドウになにも文字列を入力しない)にすることでタイトルバーが消えてくれますが、逆に Caption プロパティを""にしてないとどうしてもタイトルバーが消えてくれないです。(ほんとただ私のやり方が悪いだけなのかも。)
Caption プロパティを設定したままタイトルバーを消す方法があるのでしょうか?
> 先の投稿も一応検証してから アップしております VB6ですけどね ...
検証までして頂いてありがとうございます。
私の場合、SendMessageでWM_GETTEXTを送ると、ファイル名なのかプロジェクト名なのかわからないような名前(例えば、「abcd~1」みたいな文字列が返ってきました。)
よくわかりませんが・・・;;
度々、ありがとうございました。
No.3
- 回答日時:
> VB5にはご紹介頂いたMutexや Eventはないようです;;
「+VB +Windows +API」で Google 検索
http://www.google.co.jp/search?sourceid=navclien …
すると,↓こんなサイトが見つかりました.
「WinAPI Database for VB Programmer」は、WindowsAPIの解説を1600以上保有するサイト。
http://www.winapi-database.com/
VB5 でも API を使えるようになるかどうかは知りませんが….
使えそうであれば,次の API を探して使ってください.
・CreateMutex()
・CreateEvent()
・SetEvent()
・ResetEvent()
Windows API の VB 用宣言を集めたファイルというのを以前どこかで
見かけたことがあるので,このサイトでも探せば見つかるかもしれません.
また,ウインドウメッセージと Event を同時に待つには,メッセージループの
中で次のどちらかの API を使えば実現できますが,VB のメッセージループを
プログラマが変更できるのか,あるいは変更できないまでも,Event を待つように
指定できるのかどうかは知りません.(ここが一番難関になりそうですが.)
・MsgWaitForMultipleObjects()
・MsgWaitForMultipleObjectsEx()
ありがとうございます。
> こんなサイトが見つかりました.
便利なサイトを教えて頂いてりがとうございます。サンプルがたくさんあってわかりやすいですね。
> VB5 でも API を使えるようになるかどうかは知りませんが
VB5 でも API は使えます。
> 次の API を探して使ってください.
そういうAPIもあるんですね。
参考にさせて頂きます。
難しそうですががんばってみます。
どうもありがとうございました。
No.2
- 回答日時:
VBはどのバージョンでしょう? VB6でしょうか ...
実行ファイルの位置(パス)が同じなら PrevInstanseで確認できます
すでに起動している自分自身を見つけるには EnumWindowsのコールバックで WM_GETTEXTを引数にしてSendMessageでCaptionを取得してみましょう
Dim buf(256) as Byte
dim s as String, n as Integer
if IsWindowVisible( hWnd ) then
' IsWindowsVisibleも WinAPIです ...
SendMessage hwnd, WM_GETTEXT, 256, buf(0)
s = StrConv( buf, vbUnicode )
n = Instr( buf, char(0) )
s = left( s, n -1 )
end if
といった具合で ...
どうもありがとうございます。
すいません、VB5です。
>SendMessageでCaptionを取得してみましょう
タイトルバーがないのでCaptionもなく・・・;;
ウインドウをウインドウテキストやクラス名以外で検索する方法が、他にあるのではないかと思って質問させて頂いたのですが、簡単に一つのAPIで検索する方法はないようですね。
ダミーのコマンドボタンを貼り付けて、そのコマンドボタンを検索することで実現しようと思います。
どうもありがとうございました。
No.1
- 回答日時:
> アプリに二重起動防止機能を付けたい
二重起動防止は,Mutex を使えばできます.
.NET TIPS:Windowsアプリケーションの多重起動を禁止するには? (VB サンプルあり)
http://www.atmarkit.co.jp/fdotnet/dotnettips/145 …
> すでに起動されている場合はそのアプリのウインドウを
> 元の大きさに戻してアクティブにする
これはやったことがないのでわかりませんし,VB を知らないので VB で使えるかどうか
も知りませんが,Windows API レベルの話をすれば,Mutex と同様に名前付き Event
を使えばできそうな気がします.
(1) (名前付き) Mutex と同様に,(名前付き) Event を作成する.
(2a) (1) に失敗 (ERROR_ALREADY_EXISTS) した場合には,既にアプリケーションが起動
されている.このとき,既に作成済の Event のハンドルが得られるので,
そのイベントをシグナル状態にすることにより,最初に起動されたアプリに
二重起動されそうになったことを知らせる.
(2b) (1) に成功した場合には,メッセージループで常に上記のイベントを監視しておき,
それがシグナル状態になったらウインドウを元の大きさに戻してアクティブにする.
Windows API のレベルでは,この方法でできると思いますが,VB で Event が使えるか,
また VB のメッセージループで Event を監視する方法があるかどうかは知りません.
どうもありがとうございます。
すいません;;、バージョンを言うのを忘れていました。VB5です。
VB5にはご紹介頂いたMutexや Eventはないようです;;
.NETにはそのような機能があるのですね。
勉強になりました。
どうもありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Chrome(クローム) 最近Win10にてブラウザが左にスッと隠れていく現象に悩まされてます 3 2023/07/22 23:11
- デスクトップパソコン ん~…分からん 7 2022/06/10 10:47
- iPhone(アイフォーン) iPhone13 Pro Maxが異常に遅い理由? 3 2022/09/17 20:30
- 防犯・セキュリティ GPSトラッキングで盗難の犯人がわかった場合どうせればいい? 4 2023/02/22 07:50
- その他(OS) Win10をWin11にアップグレード、IE11は引き続き使えますか。 5 2023/01/15 06:16
- その他(インターネット接続・インフラ) アプリ利用者を特定し、裁判に 2 2022/06/09 21:43
- Android(アンドロイド) Androidってなぜ画像や動画のダウンロードがマトモにされない、出来ない、時々ダウンロードに失敗す 5 2022/08/05 23:22
- Java EclipseとVisual StudioをPC1台にインストールしただけではPCは重くならない? 3 2022/12/08 15:35
- Android(アンドロイド) いま3台のAndroidを使っています。 AndroidってiPhoneには無いmicroSDXCが 1 2022/05/06 11:42
- Windows 10 Windows 10の[アプリと機能]に表示されない旧バージョンのアプリを削除したい 1 2022/04/05 20:25
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C# の OpenFileDialog
-
WSH(VBScript)でアプリケーショ...
-
VB.NETで起動させたExcelの多重...
-
MFCアプリケーションでの終了コ...
-
MFCでコンソール出力
-
[Visual C++]VCが起動しません...
-
vbで作成したアプリをサービス...
-
vb6で異なるのプロジェクト間で...
-
Ctrl + P のメッセージ送信
-
Windowsリブート時に1回だけア...
-
アプリケーションエラー 0xc00...
-
VBにてタスクマネージャを読む方法
-
VB.NETでフォームアクティブの...
-
フレームワーク「4.8.1」で、[S...
-
外字文字の登録
-
VBSで2バイト文字の送り方の質...
-
Vba アプリケーションが立ち上...
-
outlookが強制終了してしまう
-
excel VBAで、外部アプリケーシ...
-
プログラムの二重起動防止
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コンソールアプリケーションの...
-
フレームワーク「4.8.1」で、[S...
-
Vba アプリケーションが立ち上...
-
VBSでのSendKeysでの画面の最小化
-
自分自身を更新するプログラム
-
イラストレーターCS4のシリアル...
-
Windowsプログラムのビジー状態...
-
Accessフォームからの外部アプ...
-
Console Applicationをタスクト...
-
VB.NETでMessageBoxを表示した...
-
初回接続の遅い原因について
-
pccNTmon.exeとntrtscan.exeの違い
-
vb6で異なるのプロジェクト間で...
-
WSH(VBScript)でアプリケーショ...
-
対象のアプリケーションが終了...
-
MFCアプリケーションでの終了コ...
-
VB.NETでフォームアクティブの...
-
他アプリケーションの終了
-
実行時のコマンドプロンプトを...
-
Shell関数の終了を調べる方法
おすすめ情報