Ponieważ wczoraj poimprezowałem i nie zdrowia pisać sensownego kodu a mam trochę czasu postanowiłem przyjrzeć się sprawie, która w tym przypadku jest nieco skomplikowana i rozwiązania powyżej proponowane nie zadziałają.
TNxComboBoxInspectorNode6
to tak naprawdę TNxComboBox6
tylko mający zastosowanie jako edytor właściwości komponentu TNextInspector6
, który przechwytuje komunikaty i posiada zdarzenie OnKeyPress
na które w edytorze właściwości (którym może być wspomniany ComboBox) w normalnych warunkach nie reaguje.
Próba dodania do niego obsługi komunikatu WM_CHAR
też z nieznanych przyczyn nie działa. Czyli na zwykłe dodanie zwykłe nie reaguje.
type
TNextInspector6 = class(NxInspector6.TNextInspector6)
protected
procedure WMChar(var Message: TWMChar); message WM_CHAR;
end;
Natomiast da się nadpisać zdarzenie CMChildKey
(musi być subclasing helpery nie obsługują zdarzeń)
type
TNextInspector6 = class(NxInspector6.TNextInspector6)
protected
procedure CMChildKey(var AMsg: TCMChildKey); override;
end;
//------
implementation
procedure TNextInspector6.CMChildKey(var AMsg: TCMChildKey);
var
Ref: IInterfaceComponentReference;
Comp: TComponent;
ComboBox: TNxComboBox6;
begin
inherited;
if Supports(Self.InplaceEdit, IInterfaceComponentReference, Ref) then
begin
Comp:= Ref.GetComponent;
if Comp.ClassNameIs('TNxComboBox6') then
begin
ComboBox:= TNxComboBox6(Self.InplaceEdit);
if Assigned(ComboBox) and (Assigned(Self.OnKeyPress)) then
Self.OnKeyPress(ComboBox, Char(AMsg.CharCode));
end;
end;
end;
no i oczywiście trzeba w TNextInspector6
ustawić zdarzenia OnKeyPress
na które tak przerobiony OnKeyPress
tym razem będzie reagował dla przykładu:
procedure TForm1.NextInspector61KeyPress(Sender: TObject; var Key: Char);
var
ComboBox: TNxComboBox6;
begin
if Sender is TNxComboBox6 then
begin
ComboBox:= TNxComboBox6(Sender); //abyś operowal na wlasciwym ComboBox
OutputDebugString(PChar('NxComboBox61KeyPress ' + Key));
end;
end;
Wadą rozwiązania jest to że Key jest zawsze wielką literą. Nie wiem dlaczego tak się dzieje. Nie znalazłem nic w dokumentacji aby CM_CHILDKEY
miał być wielką literą ale to pewnie dlatego że tu chodzi o klawisz a nie znak z klawiatury. Nie mamy też polskich znaków. Możliwy Fix... prawdę mówiąc wydaje mi się z D wzięty ale innego pomysłu w tej chwili (możliwe że z powodu kaca giganta) nie mam:
procedure TNextInspector6.CMChildKey(var AMsg: TCMChildKey);
const
//taką tablicę - mapę trzeba dla wszyskich wielkich liter polskich znaków
POLISH_KEYS: array [0..2,0..1] of Char = (('A', 'Ą'), ('C', 'Ć'), ('E', 'Ę'));
var
Ref: IInterfaceComponentReference;
Comp: TComponent;
ComboBox: TNxComboBox6;
MyKey: Char;
i: Integer;
begin
inherited CMChildKey(AMsg)
if Supports(Self.InplaceEdit, IInterfaceComponentReference, Ref) then
begin
Comp:= Ref.GetComponent;
if Comp.ClassNameIs('TNxComboBox6') then
begin
ComboBox:= TNxComboBox6(Self.InplaceEdit);
if Assigned(ComboBox) and (Assigned(Self.OnKeyPress)) then
begin
MyKey:= Char(AMsg.CharCode);
if ((GetKeyState(VK_RMENU) and $8000) > 0) then //polskie litery
for i:= Low(POLISH_KEYS) to High(POLISH_KEYS) do
if MyKey = POLISH_KEYS[i][0]then
begin
MyKey:= POLISH_KEYS[i][1];
break;
end;
if ((GetKeyState(VK_SHIFT) and $8000) = 0) and ((GetKeyState(VK_CAPITAL)and $0001) = 0) then //mala czy wielka
MyKey:= AnsiLowerCase(MyKey)[1];
Self.OnKeyPress(ComboBox, MyKey);
end;
end;
end;
end;
Oczywiście ta procedura uniemożliwia zmianę kodu wciśniętego klawisza jaki ma dotrzeć do ComboBox
ale na razie nie chce mi się kombinować bo to nie takie proste zwykłe AMsg.CharCode:= $41; //A
nic nie daje bez względu gdzie i czy w ogóle jest wywołanie inherited
.
.
EDIT:
Ostateczna tym razem chyba bez zarzutu funkcja dająca wpisany znak (czyli mała lub wielka litera, zwraca poprawnie polskie znaki):
procedure TNextInspector6.CMChildKey(var AMsg: TCMChildKey);
function GetCharFromKey(Key: Word): string;
var
KeybState: TKeyboardState;
KeybLayout: HKL;
begin
KeybLayout:= GetKeyboardLayout(0);
GetKeyboardState(KeybState);
SetLength(Result, 2);
ToUnicodeEx(key, key, @KeybState, @Result[1], 2, 0, KeybLayout);
end;
var
Ref: IInterfaceComponentReference;
Comp: TComponent;
ComboBox: TNxComboBox6;
MyKey: Char;
begin
inherited CMChildKey(AMsg);
if Supports(Self.InplaceEdit, IInterfaceComponentReference, Ref) then
begin
Comp:= Ref.GetComponent;
if Comp.ClassNameIs('TNxComboBox6') then
begin
ComboBox:= TNxComboBox6(Self.InplaceEdit);
if Assigned(ComboBox) and (Assigned(Self.OnKeyPress)) then
begin
MyKey:= GetCharFromKey(AMsg.CharCode)[1];
Self.OnKeyPress(ComboBox, MyKey);
end;
end;
end;
end;