3

表示されるウィンドウタイトルをコンボボックスに追加したい。これが私の情報源です:

BOOL CALLBACK EnumWindowsProc(HWND hWnd, long lParam) 
{
     TCHAR buff[255];
     CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PROCESS);
     if (IsWindowVisible(hWnd)) 
     {
         GetWindowText(hWnd, buff, 254);
         pComboBox->AddString(buff);
     }
     return TRUE;
}

void CFindProcess::OnDropdownComboProcess()
{
    EnumWindows(EnumWindowsProc, 0);
}

しかし、エラーが発生します:

error C2660: 'GetDlgItem' : function does not take 1 arguments  60

コンボにタイトルを正しく追加するにはどうすればよいですか?

4

3 に答える 3

3

MFC オブジェクトはスレッド依存でGetDlgItemあり、オブジェクトを作成したスレッド (おそらくメイン UI スレッド) で適切に機能します。関数EnumWindowsはおそらくワーカー スレッドを作成してコールバック関数にアクセスしGetDlgItemます。そのため、コンボ ボックスの有効なハンドルを取得できませんでした。

別のスレッドでコンボボックスに適切にアクセスするには、静的関数を使用する必要がありますCWnd::FromHandle。次のように、コンボボックス オブジェクトの生のハンドルを使用します。

BOOL CALLBACK EnumWindowsProc(HWND hWnd, long lParam) 
{
    if (IsWindowVisible(hWnd)) 
    {   TCHAR szBuffer[255];
        INT nLength = GetWindowText(hWnd, szBuffer, 254);
        if (nLength>0)
        {   // only add windows that has a caption
            CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle((HWND)lParam);
            pComboBox->AddString(szBuffer);
        }
    }
    return TRUE;
}

// call EnumWindows --------------------
CComboBox *pComboBox = (CComboBox *)GetDlgItem(IDC_COMBO1);
// passing the raw handle of the combobox as parameter
EnumWindows(EnumWindowsProc, (LPARAM)pComboBox->m_hWnd);
于 2013-03-10T12:52:36.673 に答える
2

ユーザー@mfcが提供したものに加えて、別のスレッドからのUI更新は行いません。列挙用のスレッドは作成されないEnumWindowsと思います。現在のスレッドのコールスタック内でコールバックを呼び出します。

これは、UIがしばらくフリーズする可能性があることを意味します。したがって、列挙用のスレッドを作成することをお勧めします。さらに、別のスレッドからUIを直接更新することはありません。vector文字列の場合もあれば、(PostMessage各反復で)私が使用したものの場合もあります。

EnumWindows非常に高速に実行される可能性があるのは事実です。しかし、ファイル、プリンター、ユーザーなどの他の(カーネル)オブジェクトを列挙するために移動すると、UIは確実にフリーズします。したがって、マルチスレッドコードを作成することをお勧めします。最初にMTコードを書くのは苦痛ですが、後でそれを気に入って感謝し、それなしでは生きていけません。

于 2013-03-10T13:06:23.900 に答える
2

まず、GetDlgItem2 つのパラメーターがあり、最初のパラメーターは、コントロールを含むダイアログ ボックスへのハンドルです。

したがって、HWNDこのコントロールを含むダイアログのパラメーターがHWND必要です。関数にパラメーターとして渡すと思います。

 CComboBox* pComboBox = (CComboBox*)GetDlgItem(hWnd,IDC_COMBO_PROCESS);
                                                 ^^^^ added parameter

EnumWindowsMSDNを見ると、コールバックを渡す必要があり、パラメーターが含まれていることがわかります。HWNDこのパラメーターの意味を見ると、次のように表示されます。

トップレベル ウィンドウへのハンドル。

これはまさにあなたが渡さなければならないものですGetDlgItem

また、渡さGetWindowTextれた に書き込まれた文字数が返されるため、 の戻り値を確認する必要がありbuffます。

     int ret = GetWindowText(hWnd, buff, 254);
     if (ret > 0) pComboBox->AddString(buff); // only add non-empty strings.
于 2013-03-09T14:38:38.163 に答える