ComboBox di Windows ordinario (stile csDropDown
o csDropDownList
) aprirà il suo elenco a discesa subito sotto o, se non vi è spazio disponibile in basso, sopra la combo. Posso controllare la posizione di questo elenco (almeno per la coordinata Y)?Posso impostare a livello di codice la posizione dell'elenco a discesa ComboBox?
risposta
pubblicazione di un esempio di codice che mostra la lista di animazione discesa correttamente e costringerà che mostra l'elenco a discesa sopra ComboBox1
. questo codice sottoclassi ComboBox hwndList
:
TForm1 = class(TForm)
ComboBox1: TComboBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FComboBoxListDropDown: Boolean;
FComboBoxListWnd: HWND;
FOldComboBoxListWndProc, FNewComboBoxListWndProc: Pointer;
procedure ComboBoxListWndProc(var Message: TMessage);
end;
....
procedure TForm1.FormCreate(Sender: TObject);
var
Info: TComboBoxInfo;
begin
ZeroMemory(@Info, SizeOf(Info));
Info.cbSize := SizeOf(Info);
GetComboBoxInfo(ComboBox1.Handle, Info);
FComboBoxListWnd := Info.hwndList;
FNewComboBoxListWndProc := MakeObjectInstance(ComboBoxListWndProc);
FOldComboBoxListWndProc := Pointer(GetWindowLong(FComboBoxListWnd, GWL_WNDPROC));
SetWindowLong(FComboBoxListWnd, GWL_WNDPROC, Integer(FNewComboBoxListWndProc));
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
SetWindowLong(FComboBoxListWnd, GWL_WNDPROC, Integer(FOldComboBoxListWndProc));
FreeObjectInstance(FNewComboBoxListWndProc);
end;
procedure TForm1.ComboBoxListWndProc(var Message: TMessage);
var
R: TRect;
DY: Integer;
begin
if (Message.Msg = WM_MOVE) and not FComboBoxListDropDown then
begin
FComboBoxListDropDown := True;
try
GetWindowRect(FComboBoxListWnd, R);
DY := (R.Bottom - R.Top) + ComboBox1.Height + 1;
// set new Y position for drop-down list: always above ComboBox1
SetWindowPos(FComboBoxListWnd, 0, R.Left, R.Top - DY , 0, 0,
SWP_NOOWNERZORDER or SWP_NOZORDER or SWP_NOSIZE or SWP_NOSENDCHANGING);
finally
FComboBoxListDropDown := False;
end;
end;
Message.Result := CallWindowProc(FOldComboBoxListWndProc,
FComboBoxListWnd, Message.Msg, Message.WParam, Message.LParam);
end;
Note:
- Sono totalmente d'accordo con David, e altri che questa è una cattiva idea quella di modificare questo comportamento predefinito specifico per
TComboBox
. OP non ha ancora risposto a perché voleva tale comportamento. - Il codice sopra è stato testato con D5/XP.
Testato con successo, grazie! – Andrew
Bene, è possibile farlo utilizzando GetComboBoxInfo
per ottenere un handle per la finestra utilizzata per l'elenco e quindi spostare quella finestra. Come questo:
type
TMyForm = class(TForm)
ComboBox1: TComboBox;
procedure ComboBox1DropDown(Sender: TObject);
protected
procedure WMMoveListWindow(var Message: TMessage); message WM_MOVELISTWINDOW;
end;
....
procedure TMyForm.ComboBox1DropDown(Sender: TObject);
begin
PostMessage(Handle, WM_MOVELISTWINDOW, 0, 0);
end;
procedure TMyForm.WMMoveListWindow(var Message: TMessage);
var
cbi: TComboBoxInfo;
Rect: TRect;
NewTop: Integer;
begin
cbi.cbSize := SizeOf(cbi);
GetComboBoxInfo(ComboBox1.Handle, cbi);
GetWindowRect(cbi.hwndList, Rect);
NewTop := ClientToScreen(Point(0, ComboBox1.Top-Rect.Height)).Y;
MoveWindow(cbi.hwndList, Rect.Left, NewTop, Rect.Width, Rect.Height, True);
end;
ho ignorato la questione del controllo degli errori per mantenere il codice semplice.
Tuttavia, si tenga presente che sembra piuttosto orribile perché l'animazione a discesa è ancora visualizzata. Forse puoi trovare un modo per disabilitarlo.
Tuttavia, non è necessario fare nulla di simile perché Windows lo fa già per te. Trascina un modulo nella parte inferiore dello schermo e trascina verso il basso la tua combo. Quindi vedrai apparire la lista sopra la combo. Come questo:
Testata in XP con D5. questo codice non funziona per me. il 'cbi.hwndList' non viene spostato. si apre e si chiude immediatamente. – kobik
@kobik Un altro motivo per non farlo. Mi aspetto che il problema sia con XP piuttosto che con D5. Probabilmente è necessario cambiare il comportamento per diverse versioni del sistema operativo. Mai un buon piano. –
Sono d'accordo al 100%. questo potrebbe probabilmente essere fatto agganciandolo a 'GWL_WNDPROC' e gestendo' WM_SIZE', ma il comportamento è così inaspettato che vorrei scaricare completamente questa idea. solo un commento a parte, penso che l'uso di 'GetComboBoxInfo' sia migliore di CB_GETCOMBOBOXINFO (vedi il commento relativo agli arresti anomali su msdn). – kobik
- 1. WPF: ComboBox senza pulsante a discesa
- 2. Come posso impostare RenderingHints a livello globale?
- 3. Android come impostare a livello di codice windowanimation
- 4. È possibile reinizializzare un CKEditor Combobox/menu a discesa?
- 5. Come impostare app: layout_scrollFlags per Toolbar a livello di codice
- 6. Come impostare a livello di codice maxLength in Android TextView?
- 7. WPF Style Combobox con due colonne nel menu a discesa
- 8. Come impostare windowDrawsSystemBarBackgrounds a livello di programmazione?
- 9. cambia posizione nell'elenco a discesa spinner
- 10. Come impostare i margini per TextView a livello di codice?
- 11. Come impostare l'immagine come sfondo a livello di codice?
- 12. Impossibile impostare DropDownHeight di ComboBox
- 13. menu a discesa javafx combobox esce dai bordi dello schermo
- 14. Ottieni codice identificativo a livello di codice
- 15. Posso eseguire l'override di Google SERP con determinazione automatica della posizione IP a livello di codice?
- 16. Come aggiungere i vincoli a livello di codice a un UIView creato a livello di codice?
- 17. Interruttore a discesa multi-livello UI angolare
- 18. Scorrimento a livello di codice
- 19. Come selezionare una voce dell'elenco a discesa per valore a livello di codice
- 20. Impostare NSWindow Size a livello di programmazione
- 21. caso ComboBox discesa sensitive
- 22. Come cambio la posizione del menu a discesa dat.gui?
- 23. Impostare NOCOUNT OFF a livello di database?
- 24. Ottieni la velocità di collegamento a livello di codice?
- 25. Imposta larghezza vista a livello di codice
- 26. Facebook: posso aggiungere un amico a livello di codice?
- 27. Posso usare T4 a livello di codice da C#?
- 28. Come posso comporre un messaggio a livello di codice?
- 29. Come posso aggiungere un contatto a livello di codice?
- 30. Android: come impostare a livello di codice la larghezza di ImageView all'interno di TableRow
Basta chiedersi: perché? Cosa nel comportamento predefinito non è di tuo gradimento? –
@ MarjanVenema Il nostro progettista desidera migliorare l'usabilità per la casella combinata owner-draw – Andrew