システムメンテナンスのお知らせ

今、タイトルバーのないアプリを作っているのですが、このアプリのウインドウを別アプリから、APIのFindWindow関数で見つけたいのですが、タイトルがないのでクラス名でしか見つけれません。同じクラスのウインドウが他にもあった場合、区別が付かず困っています。

具体的に申しますと、作ったアプリに二重起動防止機能を付けたい(すでに起動されている場合はそのアプリのウインドウを元の大きさに戻してアクティブにする)のですが、そのアプリにはタイトルバーがなく、FindWindowでは見つけれない場合があります。

このような場合どうすればいいでしょうか?
よろしくお願い致します。

gooドクター

A 回答 (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ファイルにして実行して確認してください。
    • good
    • 0
この回答へのお礼

うぉ~~、 すごい~!!
ありがとうございます。

ThunderRT5Mainに書き換えたら動きました。

> これは、VBのEXEで実行時にクラス名が ThunderRT6Main で
> キャプションがプロジェクトのプロパティの実行ファイルの作成タブの
> アプリケーションのタイトル(=App.Title=タスクマネージャのタスク
> に表示されるタスク名)のウィンドウが必ず存在するので

そのようなウインドウが存在するとは知りませんでした!!

App.Titleを実行中に変更できるなんて思いもしませんでした。

おかげさまでシンプルなコードになりました。

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


尚、ここで解決とさせて頂きます。
いろいろとごご教授くださった皆様、
どうもありがとうございました。

お礼日時:2007/01/05 20:15

フォームの外枠を可変にしたいのでしょうか?


そうなると ControlBoxとCaptionで操作することになりますね

固定でよいのなら BorderStyleを 0の無しに設定してみてはいかがでしょう
これなら Captionは設定してあっても タイトルバーは表示されませんよ
    • good
    • 0
この回答へのお礼

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

> BorderStyleを 0の無しに設定してみてはいかがでしょう

そうすると今度はタスクバーにも表示されなくなってしまうので・・・;;

noocyteさんが教えてくださったMutexを使ったやり方はむずかしかったので、ダミーのコマンドボタンを貼り付けるやり方で実現しました。

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

お礼日時:2006/12/31 20:18

>>SendMessageでCaptionを取得してみましょう


>タイトルバーがないのでCaptionもなく・・・;;

タイトルバーがなくても 作成したアプリケーションのフォームのCaptionプロパティが設定されているのであれば
WM_GETTEXTで取得できる場合がありますよ
先の投稿も一応検証してから アップしております VB6ですけどね ...
    • good
    • 0
この回答へのお礼

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

> タイトルバーがなくても 作成したアプリケーションのフォームのCaptionプロパティが設定されているのであればWM_GETTEXTで取得できる場合がありますよ

VB5でフォームのCaptionプロパティを設定するとタイトルバーがなくならないです。(私のやり方が悪いのかも。)

フォームのControlBox プロパティを False にして、Caption プロパティを ""(プロパティウインドウになにも文字列を入力しない)にすることでタイトルバーが消えてくれますが、逆に Caption プロパティを""にしてないとどうしてもタイトルバーが消えてくれないです。(ほんとただ私のやり方が悪いだけなのかも。)

Caption プロパティを設定したままタイトルバーを消す方法があるのでしょうか?

> 先の投稿も一応検証してから アップしております VB6ですけどね ...

検証までして頂いてありがとうございます。
私の場合、SendMessageでWM_GETTEXTを送ると、ファイル名なのかプロジェクト名なのかわからないような名前(例えば、「abcd~1」みたいな文字列が返ってきました。)
よくわかりませんが・・・;;

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

お礼日時:2006/12/31 00:02

> 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()
    • good
    • 0
この回答へのお礼

ありがとうございます。

> こんなサイトが見つかりました.

便利なサイトを教えて頂いてりがとうございます。サンプルがたくさんあってわかりやすいですね。

> VB5 でも API を使えるようになるかどうかは知りませんが

VB5 でも API は使えます。

> 次の API を探して使ってください.

そういうAPIもあるんですね。
参考にさせて頂きます。

難しそうですががんばってみます。
どうもありがとうございました。

お礼日時:2006/12/30 19:57

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
といった具合で ...
    • good
    • 0
この回答へのお礼

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

すいません、VB5です。

>SendMessageでCaptionを取得してみましょう
タイトルバーがないのでCaptionもなく・・・;;

ウインドウをウインドウテキストやクラス名以外で検索する方法が、他にあるのではないかと思って質問させて頂いたのですが、簡単に一つのAPIで検索する方法はないようですね。

ダミーのコマンドボタンを貼り付けて、そのコマンドボタンを検索することで実現しようと思います。

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

お礼日時:2006/12/30 10:50

> アプリに二重起動防止機能を付けたい



二重起動防止は,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 を監視する方法があるかどうかは知りません.
    • good
    • 0
この回答へのお礼

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

すいません;;、バージョンを言うのを忘れていました。VB5です。

VB5にはご紹介頂いたMutexや Eventはないようです;;

.NETにはそのような機能があるのですね。
勉強になりました。

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

お礼日時:2006/12/30 08:21

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

gooドクター

人気Q&Aランキング