• ベストアンサー

タイトルバーのないアプリに二重起動防止機能を付けたい

今、タイトルバーのないアプリを作っているのですが、このアプリのウインドウを別アプリから、APIのFindWindow関数で見つけたいのですが、タイトルがないのでクラス名でしか見つけれません。同じクラスのウインドウが他にもあった場合、区別が付かず困っています。 具体的に申しますと、作ったアプリに二重起動防止機能を付けたい(すでに起動されている場合はそのアプリのウインドウを元の大きさに戻してアクティブにする)のですが、そのアプリにはタイトルバーがなく、FindWindowでは見つけれない場合があります。 このような場合どうすればいいでしょうか? よろしくお願い致します。

noname#208339
noname#208339

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

  • ベストアンサー
回答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ファイルにして実行して確認してください。

noname#208339
質問者

お礼

うぉ~~、 すごい~!! ありがとうございます。 ThunderRT5Mainに書き換えたら動きました。 > これは、VBのEXEで実行時にクラス名が ThunderRT6Main で > キャプションがプロジェクトのプロパティの実行ファイルの作成タブの > アプリケーションのタイトル(=App.Title=タスクマネージャのタスク > に表示されるタスク名)のウィンドウが必ず存在するので そのようなウインドウが存在するとは知りませんでした!! App.Titleを実行中に変更できるなんて思いもしませんでした。 おかげさまでシンプルなコードになりました。 どうもありがとうございました。 尚、ここで解決とさせて頂きます。 いろいろとごご教授くださった皆様、 どうもありがとうございました。

その他の回答 (5)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.5

フォームの外枠を可変にしたいのでしょうか? そうなると ControlBoxとCaptionで操作することになりますね 固定でよいのなら BorderStyleを 0の無しに設定してみてはいかがでしょう これなら Captionは設定してあっても タイトルバーは表示されませんよ

noname#208339
質問者

お礼

どうもありがとうございます。 > BorderStyleを 0の無しに設定してみてはいかがでしょう そうすると今度はタスクバーにも表示されなくなってしまうので・・・;; noocyteさんが教えてくださったMutexを使ったやり方はむずかしかったので、ダミーのコマンドボタンを貼り付けるやり方で実現しました。 いろいろとありがとうございました。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

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

noname#208339
質問者

お礼

何度も、ありがとうございます。 > タイトルバーがなくても 作成したアプリケーションのフォームのCaptionプロパティが設定されているのであればWM_GETTEXTで取得できる場合がありますよ VB5でフォームのCaptionプロパティを設定するとタイトルバーがなくならないです。(私のやり方が悪いのかも。) フォームのControlBox プロパティを False にして、Caption プロパティを "" (プロパティウインドウになにも文字列を入力しない)にすることでタイトルバーが消えてくれますが、逆に Caption プロパティを""にしてないとどうしてもタイトルバーが消えてくれないです。(ほんとただ私のやり方が悪いだけなのかも。) Caption プロパティを設定したままタイトルバーを消す方法があるのでしょうか? > 先の投稿も一応検証してから アップしております VB6ですけどね ... 検証までして頂いてありがとうございます。 私の場合、SendMessageでWM_GETTEXTを送ると、ファイル名なのかプロジェクト名なのかわからないような名前(例えば、「abcd~1」みたいな文字列が返ってきました。) よくわかりませんが・・・;; 度々、ありがとうございました。

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.3

> VB5にはご紹介頂いたMutexや Eventはないようです;; 「+VB +Windows +API」で Google 検索 http://www.google.co.jp/search?sourceid=navclient-ff&ie=UTF-8&rls=GGGL,GGGL:2006-34,GGGL:ja&q=%2BVB+%2BWindows+%2BAPI すると,↓こんなサイトが見つかりました. 「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()

noname#208339
質問者

お礼

ありがとうございます。 > こんなサイトが見つかりました. 便利なサイトを教えて頂いてりがとうございます。サンプルがたくさんあってわかりやすいですね。 > VB5 でも API を使えるようになるかどうかは知りませんが VB5 でも API は使えます。 > 次の API を探して使ってください. そういうAPIもあるんですね。 参考にさせて頂きます。 難しそうですががんばってみます。 どうもありがとうございました。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答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 といった具合で ...

noname#208339
質問者

お礼

どうもありがとうございます。 すいません、VB5です。 >SendMessageでCaptionを取得してみましょう タイトルバーがないのでCaptionもなく・・・;; ウインドウをウインドウテキストやクラス名以外で検索する方法が、他にあるのではないかと思って質問させて頂いたのですが、簡単に一つのAPIで検索する方法はないようですね。 ダミーのコマンドボタンを貼り付けて、そのコマンドボタンを検索することで実現しようと思います。 どうもありがとうございました。

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.1

> アプリに二重起動防止機能を付けたい 二重起動防止は,Mutex を使えばできます. .NET TIPS:Windowsアプリケーションの多重起動を禁止するには? (VB サンプルあり) http://www.atmarkit.co.jp/fdotnet/dotnettips/145winmutex/winmutex.html > すでに起動されている場合はそのアプリのウインドウを > 元の大きさに戻してアクティブにする これはやったことがないのでわかりませんし,VB を知らないので VB で使えるかどうか も知りませんが,Windows API レベルの話をすれば,Mutex と同様に名前付き Event を使えばできそうな気がします. (1) (名前付き) Mutex と同様に,(名前付き) Event を作成する. (2a) (1) に失敗 (ERROR_ALREADY_EXISTS) した場合には,既にアプリケーションが起動 されている.このとき,既に作成済の Event のハンドルが得られるので, そのイベントをシグナル状態にすることにより,最初に起動されたアプリに 二重起動されそうになったことを知らせる. (2b) (1) に成功した場合には,メッセージループで常に上記のイベントを監視しておき, それがシグナル状態になったらウインドウを元の大きさに戻してアクティブにする. Windows API のレベルでは,この方法でできると思いますが,VB で Event が使えるか, また VB のメッセージループで Event を監視する方法があるかどうかは知りません.

noname#208339
質問者

お礼

どうもありがとうございます。 すいません;;、バージョンを言うのを忘れていました。VB5です。 VB5にはご紹介頂いたMutexや Eventはないようです;; .NETにはそのような機能があるのですね。 勉強になりました。 どうもありがとうございました。

関連するQ&A

  • アプリがタイトルバーだけで起動する

    特定のアプリのウィンドウの初期状態が画像のようにタイトルバーのみになってしまいました。 下方向にドラッグして引き延ばせば問題なくアプリを使用できるのですが、いちいちその作業をするのは面倒ですし他のアプリのタイトルバーとかぶってしまうと起動したことに気づきにくいです。元に戻したいのですが、どうすればよいのでしょうか。

  • プログラムの二重起動防止

    プログラムの二重起動を防止したいんですが、V.B.のようにjavaにも、二重防止の関数があるのでしょうか? あるとすれば、どういったものなのでしょうか?

    • ベストアンサー
    • Java
  • ウィンドウのタイトルバーの高さ

    ウィンドウのタイトルバーの高さを2倍にしタイトルの文字の大きさを2倍にしたいのですがそのようなことをAPIでできるのでしょうか?

  • VBAでのタイトルバーの取得

    vbaを使ってエクセルのセルのデータを起動済みの他のアプリケーション(以下他アプリ)に貼り付けたいと考えています。 具体的には、↓のようなものを作りたいと考えています。 Sub CopyCell()  Cells(2, 1).Copy  AppActivate ("タイトル")  SendKeys "^v", True End Sub そこで上記のようにAppActivateを使用して他アプリをアクティブにしようと思っています。しかし、AppActivateに必要になる、他アプリのウィンドウのタイトルがそのときどきによって変わる為、それに対処したいのですがなかなかうまくいかず困っています。 調べたところによると、API関数のGetWindowTextを使用すればそれが可能であるとのことでした。ただ、私は完全な初心者なのでAPIの使用方法や複数同時起動しているアプリケーションの中からアプリだけを選ぶ方法がまったくわかりません。 どなたかおわかりになる方いましたらよろしくお願い致します。 具体的なソースを貼って頂けると大変助かります。

  • サーバ・クライアント環境で2重起動防止したい

    現在、2重起動防止の機能を考えています。 システムとしてはサーバー(Win2003Server)にアプリを置いて、クライアント(WinXP)からリモート接続で繋いでそのアプリを起動します。この時、クライアント1にてアプリを実行していた場合はサーバ及び他クライアントではアプリを起動できないようにしたい。 CreateMutexとWaitForSingleObjectで出来るかと思ったのですが、(作り方が悪いのか)出来ませんでした。(x_x) VC++6.0を使用しています。VBの経験はそれなりにありますが、VCは初心者です。 よろしくお願いいたします。

  • タイトルバーと同機能のスタティックコントロール

    VC6.0 MFC ダイアログで常駐アプリを作っているものです。 タイトルバーを非表示にし、タイトルバーに似せたビットマップを 作成し、スタティックコントロールに貼り付けています。 そこで、このビットマップにタイトルバーと同様の機能をもたせたいのですが、 タイトルバー上をドラッグ&ドロップでウィンドウを移動させる方法が どうしてもわかりません。 ウィンドウを移動させる方法はわかっているのですが、 スタティックコントロールに機能を実装する事ができません。 どなたかご教授ください。よろしくお願い致します。   

  • ウィンドウタイトルの取得方法

    WIN98 MFC vc++6.0 2重起動を防止し、既に起動している時は、ウィンドウを最上位にもってくる以下のコードにて ウィンドウのタイトルを設定しているIDS_WINDOWTITLEはどこで定義し、どうやってタイトルを設定すれば良いのでしょうか? BOOL CMyApp::InitInstance() { 略  // アプリケーションの二重起動防止  ::CreateMutex(NULL, TRUE, m_pszExeName);  if( GetLastError() == ERROR_ALREADY_EXISTS) {   // 既に起動されている場合は、CWnd::FindWindow関数を使って   // 起動されているアプリケーションのウィンドウを取得し、   // そのウィンドウを最上位へ持ってくる   CString str;   str.LoadString(IDS_WINDOWTITLE);   // IDS_WINDOWTITLEにはウィンドウのタイトルを設定している   CWnd* pWnd = CWnd::FindWindow(NULL, str);   if( pWnd )   pWnd->SetForegroundWindow();   return FALSE;  }

  • VB6 二重起動確実防止について

    VB6 SP5にて2重起動確実な防止処理をいれようとCreateMutex 関数を使用しようと思っています。 CreateMutex 関数を埋め込んでEXEを実行すると 実際に対象となるプログラムが起動しているにも関わらず起動してしまいます。 何がいけないのか?検討がつかず困っています。 下記がプログラムになります。 何かわかりましたらご回答の程、よろしくお願い致します。 ***Win32API**************** Option Explicit ' CreateMutex 関数 Private Declare Function CreateMutex Lib "KERNEL32.DLL" Alias "CreateMutexA" ( _ ByRef lpMutexAttributes As Long, _ ByVal bInitialOwner As Long, _ ByVal lpName As String _ ) As Long ' CloseHandle 関数 Private Declare Function CloseHandle Lib "KERNEL32.DLL" ( _ ByVal hObject As Long _ ) As Long ************************************ SUB MAIN********************************* Public Sub Main() Dim hMutex As Long hMutex = CreateMutex(ByVal 0&, 0&, App.Title) On Error GoTo Err_Main If Err.LastDllError = 0 Then Dim cForm As Form1 Set cForm = New Form1 Call cForm.Show(vbModal) End If Err_Main: If hMutex <> 0 Then Call CloseHandle(hMutex) End If End Sub ************************************************

  • VB5.0 二重起動防止

    OSWin98/VB5.0を使用しています。同一のシステムの重複起動を防止したいのです。過去ログの、 http://oshiete1.goo.ne.jp/kotaeru.php3?q=644390 を参照し、 http://www.vbvbvb.com/jp/gtips/1101/gCreateToolhelp32SnapshotTh32csSnapprocess.html のサンプルを参考にし、実行中のプロセスに同一のものがあれば、複数起動と判断するようにしました。 しかし、どうしても二重起動されてしまいます。 例1)A.exeを起動、A.vbpをデバッグで実行    →二重起動を検出し、後者は起動されない 例2)A.exeを起動、A.exeを起動    →二重起動が検出されず、後者も起動されてしまう App.PrevInstanceで判断できると思うのですが、例1と同じ方法でもこの場合は、二重起動を防ぐことができません。 他によい方法がある、ここがおかしいんじゃないの?等ありましたら、教えてください。 よろしくお願いします。

  • ニッソールームメイトのヒーターは空焚き防止機能付き?

    タイトルの通りなんですがニッソールームメイトに内蔵されているヒーターには空焚き防止機能がついているでしょうか?またそうだとしたら再起動できるタイプですか?

専門家に質問してみよう