普通的Windows ComboBox(csDropDown或csDropDownList样式)将在其下方打开其下拉列表,如果下方没有空格,则在组合上方打开.我可以控制此列表的位置(至少按Y坐标)吗?
解决方法
发布将正确显示下拉列表动画的代码示例,并强制显示ComboBox1上方的下拉列表.这个代码子类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,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,R.Left,R.Top - DY,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;
笔记:
>我完全同意David和其他人的意见,这对于改变TComboBox的这种特定默认行为是一个坏主意. OP尚未回应为什么他想要这样的行为.>上面的代码是用D5 / XP测试的.