ホーム » MFC » WM_COPYDATA

WM_COPYDATA

色々と調べていて WM_COPYDATA を見つけた.それで Gemini に聞きながらやってみた.
動作としては次の様なもの.
* アプリの重複起動を防ぐ
* 2つ目の exe が受け取った引数を 1つ目に統合
* 1つ目の exe のリストボックスにその引数を追加


プロジェクト名は wmcpd とした.
リソースエディタでリストボックス IDC_LIST1 を追加.

// wmcpd.h

#define MY_APP_CLASSNAME _T("WMCPD_MG_CLASS")
#define MY_MUTEX_NAME    _T("WMCPD_MUTEX")

// wmcpd.cpp
BOOL CWmcpdApp::InitInstance()
{
    ::CreateMutex(NULL, FALSE, MY_MUTEX_NAME);
    if (::GetLastError() == ERROR_ALREADY_EXISTS)    {  // CreateMutex で多重起動のチェック
        HWND hWnd = ::FindWindow(MY_APP_CLASSNAME, NULL);
        if (hWnd != NULL)        {
            for (int i = 1; i < __argc; ++i)            {
                COPYDATASTRUCT cds;    //  プロセス境界を越えて文字列を渡すための標準的な構造体
                cds.dwData = 0;
                cds.cbData = (::lstrlen(__targv[i]) + 1) * sizeof(TCHAR);
                cds.lpData = __targv[i];
                ::SendMessage(hWnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
            }
            ::SetForegroundWindow(hWnd);
        }
        return FALSE; 
    }

    WNDCLASS wc;
    ::GetClassInfo(AfxGetInstanceHandle(), _T("#32770"), &wc); // ダイアログのデフォルト
    wc.lpszClassName = MY_APP_CLASSNAME;
    wc.hInstance = AfxGetInstanceHandle();
    ::RegisterClass(&wc);     //  FindWindow で自ウィンドウを見つけるためにクラス名を定義

    CWmcpdDlg dlg;
//  ...
    return FALSE;
}

// wmcpdDlg.cpp

BEGIN_MESSAGE_MAP(CWmcpdDlg, CDialog)
    //{{AFX_MSG_MAP(CWmcpdDlg)
    // ...
    ON_WM_COPYDATA()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CWmcpdDlg::OnInitDialog()
{
//  ...
    CListBox* pList = (CListBox*)GetDlgItem(IDC_LIST1);
    if (pList != NULL)    {
        for (int i = 1; i < __argc; ++i)        {
            pList->AddString(__targv[i]);
        }
    }
    return TRUE;
}

BOOL CWmcpdDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
    if (pCopyDataStruct->dwData == 0)    {
        LPCTSTR pszData = (LPCTSTR)pCopyDataStruct->lpData;
        CListBox* pList = (CListBox*)GetDlgItem(IDC_LIST1);
        if (pList != NULL && pszData != NULL)        {
            pList->AddString(pszData);
        }
    }
    return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}

最初,ダイアログのクラス名を指定する方法がわからなかったので,そのまま実行させた.
すると, HWND hWnd = ::FindWindow(MY_APP_CLASSNAME, NULL); で NULL が返ってくる.
クラス名を設定していないのでデフォルトの #32770
それを Gemini に問い合わせると,次の様に返ってきた.

// wmcpd.rc の例
IDD_WMCPD_DIALOG DIALOG DISCARDABLE  0, 0, 182, 92
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "wmcpd"
CLASS "WMCPD_MG_CLASS"  // ←これを手動で追加
FONT 9, "MS UI Gothic"
BEGIN
    // ...
END

ダイアログのクラス名を WMCPD_MG_CLASS に
これで意図した動作になった.
https://itl.mish.work/i_Tools/Doc/blog/vc/wmcpd.zip

この投稿は役に立ちましたか ? 0 人中 0 人がこの 投稿 は役に立ったと言っています。
© 2009-2026 mish.work All Rights Reserved.

Powered by WordPress / Academica WordPress Theme by WPZOOM