Frage

Ich habe eine WTL-Anwendung, die eine erweiterte Combobox Steuerung (die Win32-Klasse ComboBoxEx32) mit dem CBS_DROPDOWNLIST Stil verwendet. Es funktioniert gut (ich kann in der Box haben Bilder gegen jedes Element), aber das Verhalten der Tastatur unterscheidet sich von einem normalen Combobox - durch Drücken einer Taste nicht in der Combo auf das erste Element springen, dass beginnt mit diesem Buchstaben

.

Zum Beispiel, wenn ich die Saiten ‚Arnold‘, ‚Bob‘ und ‚Charlie‘ zu der Combo hinzufügen, wenn ich wählen Sie dann die Combo und drücken Sie ‚B‘, dann ‚Bob‘ nicht ausgewählt werden.

Wer weiß, wie diese Arbeit zu machen? Derzeit ist die einzige Idee, die ich denken kann irgendwie ist die Combobox ‚tatsächliche‘ Unterklasse (ich kann den Griff bekommen dies die CBEM_GETCOMBOCONTROL Nachricht verwenden) und Prozess WM_CHARTOITEM. Dies ist ein PITA so dass ich dachte, ich würde fragen, ob jemand über dieses Problem hat sich vor.

War es hilfreich?

Lösung

Am Ende hakte ich die Combobox-Steuerung (mit CBEM_GETCOMBOCONTROL erhalten) und die WM_CHARTOITEM Nachricht gefangen und führte meinen eigenen Nachschlag. Ich kann Code schreiben, wenn jemand interessiert ist.

Andere Tipps

Ich habe eine Arbeitslösung und will zu teilen, dass:

ComboBoxExKeyboardSupport.h

#pragma once

class CComboBoxExKeyboardSupport
{
// Construction
public:
    CComboBoxExKeyboardSupport( void );
    ~CComboBoxExKeyboardSupport( void );

// Attributes
private:
    static CSimpleMap<HWND, CComboBoxExKeyboardSupport*> responsibleMap;

    HWND hComboBoxHwnd;
    WNDPROC fpOriginalWndProc;

// Operations
private:
    static LRESULT CALLBACK StaticWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
    LRESULT WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
    LRESULT HandleCharToItemMessage( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

    bool IsWindowsXPPlatform( void );
    bool InputMatches( CString inputChar, CString& itemText );

public:
    void Attach( CComboBoxEx& comboBoxEx );
    void Detach( void );
};

ComboBoxExKeyboardSupport.cpp

#include "StdAfx.h"
#include "ComboBoxExKeyboardSupport.h"

// Static member
CSimpleMap<HWND, CComboBoxExKeyboardSupport*> CComboBoxExKeyboardSupport::responsibleMap;

CComboBoxExKeyboardSupport::CComboBoxExKeyboardSupport( void )
{
    hComboBoxHwnd = nullptr;
    fpOriginalWndProc = nullptr;
}

CComboBoxExKeyboardSupport::~CComboBoxExKeyboardSupport( void )
{
    Detach( );
}

void CComboBoxExKeyboardSupport::Attach( CComboBoxEx& comboBoxEx )
{
    ATLASSERT( hComboBoxHwnd == nullptr );
    if( hComboBoxHwnd != nullptr )
        return;

    if( !IsWindowsXPPlatform( ) )
        return;

    LONG_PTR lpNewWndProc = reinterpret_cast<LONG_PTR>( StaticWndProc );
    LONG_PTR lpOldWndProc = 0;

    //----
    hComboBoxHwnd = comboBoxEx.GetComboBoxCtrl( )->GetSafeHwnd( );
    ATLASSERT( hComboBoxHwnd != nullptr );

    // Exchange the WndProc
    lpOldWndProc = SetWindowLongPtr( hComboBoxHwnd, GWLP_WNDPROC, lpNewWndProc );
    ATLASSERT( lpOldWndProc != 0 );
    fpOriginalWndProc = reinterpret_cast<WNDPROC>( lpOldWndProc ); 

    // Remember the handle and the old WndProc
    responsibleMap.Add( hComboBoxHwnd, this );
}

void CComboBoxExKeyboardSupport::Detach( void )
{
    if( hComboBoxHwnd == nullptr )
        return;

    //----
    LONG_PTR lpResult = 0;

    // Reset original WndProc
    lpResult = SetWindowLongPtr( hComboBoxHwnd, GWLP_WNDPROC,
        reinterpret_cast<LONG_PTR>( fpOriginalWndProc ) );
    ATLASSERT( lpResult != 0 );

    // Remove handle and WndProc from map
    responsibleMap.Remove( hComboBoxHwnd );

    //----
    hComboBoxHwnd = nullptr;
    fpOriginalWndProc = nullptr;
}

bool CComboBoxExKeyboardSupport::IsWindowsXPPlatform( void )
{
    OSVERSIONINFO osvi = {0};
    bool bResult = false;

    //----
    osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
    if( GetVersionEx( &osvi ) )
    {
        // 5.1 = Windows XP
        // 5.2 = Windows Server 2003, Windows Server 2003 R2
        bResult = ( osvi.dwMajorVersion == 5 &&
            ( osvi.dwMinorVersion == 1 || osvi.dwMinorVersion == 2 ) );
    }

    return bResult;
}

LRESULT CComboBoxExKeyboardSupport::StaticWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    CComboBoxExKeyboardSupport* pResponsibleClass = nullptr;

    // Get responsible class from map
    pResponsibleClass = responsibleMap.Lookup( hwnd );
    ATLASSERT( pResponsibleClass != nullptr );

    //----
    return pResponsibleClass->WndProc( hwnd, uMsg, wParam, lParam );
}

LRESULT CComboBoxExKeyboardSupport::WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    // Save originalWndProc because after WM_DESTROY/Detach the member variable is nullptr.
    WNDPROC fpOriginalWndProc = this->fpOriginalWndProc;

    //----
    if( uMsg == WM_DESTROY )
    {
        Detach( );
    }
    else if( uMsg == WM_CHARTOITEM )
    {
        return HandleCharToItemMessage( hwnd, uMsg, wParam, lParam );
    }

    //----
    return ::CallWindowProc( fpOriginalWndProc, hwnd, uMsg, wParam, lParam );
}

LRESULT CComboBoxExKeyboardSupport::HandleCharToItemMessage(
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam )
{
    //----
    LRESULT lResult = CB_ERR;
    CComboBox* pComboBox = nullptr;
    int itemCount = 0;
    int itemSelected = 0;
    CString itemText;
    TCHAR inputCharacter = 0;

    //----
    pComboBox = (CComboBox*)CComboBox::FromHandle( hwnd );

    //----
    itemCount = pComboBox->GetCount( );
    itemSelected = pComboBox->GetCurSel( );
    inputCharacter = static_cast<TCHAR>( LOWORD( wParam ) );

    // Search from the current selected item plus one to the end
    for( int i = (itemSelected + 1); i < itemCount; i++ )
    {
        pComboBox->GetLBText( i, itemText );
        if( InputMatches( inputCharacter, itemText ) )
        {
            lResult = i;
            break;
        }
    }

    if( lResult == CB_ERR )
    {
        // Search from the beginning to the selected item minus one.
        for( int i = 0; i < itemSelected; i++ )
        {
            pComboBox->GetLBText( i, itemText );
            if( InputMatches( inputCharacter, itemText ) )
            {
                lResult = i;
                break;
            }
        }
    }

    //----
    return lResult;
}

bool CComboBoxExKeyboardSupport::InputMatches( CString inputChar, CString& itemText )
{
    CString firstCharString;
    bool bInputMatches = false;

    //----
    firstCharString = itemText;
    firstCharString.Left( 1 );

    //----
    bInputMatches = firstCharString.CompareNoCase( inputChar ) == 0;

    //----
    return bInputMatches;
}

Mein Vorschlag ist CComboBoxEx zu Graben und auf das Symbol mit inhaber ziehen regelmäßige Kombinationsfeld zu ziehen. CComboBoxEx unterscheidet sich geringfügig von der ‚normalen‘ Combobox aber gerade genug Möglichkeiten, dass ich es ist eine komplette Neuimplementierung vermuten. Beachten Sie, wie ein ausgewähltes Element sieht etwas anders aus einem, in einem normalen Kombinationsfeld ausgewählt ist, wie gut.

Besitzer Kontrollen in WTL ziehen sind ganz einfach mit dem COwnerDraw mixin zu implementieren.

keine Antwort auf Ihre Frage, nur dass Sie wissen, dass das ist, wie ich umgehen CComboBoxEx heute:)

In unserer Anwendung, die das Verhalten der Tastatur Sie beschrieben wurde zwischen den Versionen verloren. Wie sich herausstellt, entfernt wir eine zusätzliche Manifest Abhängigkeit, die auf einer älteren Version von comctl32.dll in einer Abhängigkeit geführt (5,82). Diese Zeile in den Projekteinstellungen, Konfigurationseigenschaften -> Linker -> Manifest Datei -> Zusätzliche Manifest Abhängigkeiten:

type = 'win32' name = 'Microsoft.Windows.Common-Controls version = '6.0.0.0' processor = '' PublicKeyToken = '6595b64144ccf1df' language ='

reparierte es für uns.

Mit Dependency Walker, kann man prüfen, ob die App ist jetzt nur noch abhängig von COMCTL32.DLL Version 6.10, die das richtige Verhalten hat.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top