साधारण विंडोज कॉम्बोबॉक्स (csDropDown
या csDropDownList
शैली) कॉम्बो के ऊपर, नीचे कोई स्थान नहीं छोड़ा गया है, या नीचे अपनी ड्रॉपडाउन सूची खुल जाएगा। क्या मैं इस सूची की स्थिति को नियंत्रित कर सकता हूं (कम से कम वाई समन्वय द्वारा)?क्या मैं प्रोग्रामेटिक रूप से कॉम्बोबॉक्स ड्रॉपडाउन सूची की स्थिति निर्धारित कर सकता हूं?
उत्तर
एक कोड उदाहरण है कि ड्रॉप-डाउन सूची एनीमेशन सही ढंग से दिखाई देगा और ComboBox1
ऊपर ड्रॉप-डाउन सूची दिखा बाध्य करेगा पोस्ट करना।
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;
नोट: इस कोड ComboBox hwndList
उपवर्गों
- मैं पूरी तरह दाऊद से सहमत हैं, और दूसरों है कि यह एक बुरा विचार
TComboBox
के लिए इस विशिष्ट डिफ़ॉल्ट व्यवहार को बदलने के लिए है। ओपी ने अभी तक का जवाब नहीं दिया है क्यों वह ऐसा व्यवहार चाहता था। - उपरोक्त कोड का परीक्षण डी 5/एक्सपी के साथ किया गया था।
पर सफलतापूर्वक परीक्षण किया है, धन्यवाद! – Andrew
ठीक है, आप सूची के लिए उपयोग की गई विंडो में हैंडल प्राप्त करने के लिए GetComboBoxInfo
का उपयोग कर ऐसा कर सकते हैं, और फिर उस विंडो को ले जाएं। इस तरह:
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;
मैंने कोड को सरल रखने के लिए त्रुटि जांच के मुद्दे को अनदेखा कर दिया है।
हालांकि, चेतावनी दी जानी चाहिए कि यह बहुत भयानक लग रहा है क्योंकि ड्रॉपडाउन एनीमेशन अभी भी दिखाया गया है। शायद आप इसे अक्षम करने का एक तरीका ढूंढ सकते हैं।
हालांकि, आपको बस ऐसा कुछ करने की आवश्यकता नहीं है क्योंकि विंडोज़ पहले से ही आपके लिए यह करता है। एक फॉर्म को स्क्रीन के नीचे खींचें और अपना कॉम्बो ड्रॉप करें। फिर आप सूची को कॉम्बो के ऊपर दिखाई देंगे। इस तरह:
के लिए कुछ उपयोगिता सुधार करना चाहते हैं। यह कोड मेरे लिए काम नहीं कर रहा है। 'cbi.hwndList' स्थानांतरित नहीं किया जा रहा है। यह तुरंत खुलता है और बंद हो जाता है। – kobik
@kobik फिर भी ऐसा करने का एक अन्य कारण नहीं है। मुझे उम्मीद है कि यह मुद्दा डी 5 के बजाय एक्सपी के साथ है। आपको शायद विभिन्न ओएस संस्करणों के लिए व्यवहार स्विच करने की आवश्यकता है। कभी अच्छी योजना नहीं है। –
मैं 100% सहमत हूं। यह शायद 'GWL_WNDPROC' को हुक करके और 'WM_SIZE' को संभालने के द्वारा किया जा सकता है, लेकिन व्यवहार इतना अप्रत्याशित है कि मैं इस विचार को पूरी तरह से डंप कर दूंगा। सिर्फ एक तरफ टिप्पणी, मुझे लगता है कि 'GetComboBoxInfo' का उपयोग सीबी_जीईटीसीएमबीओबीएक्सआईएफओओ से बेहतर है (एमएसडीएन पर दुर्घटनाओं के बारे में टिप्पणी देखें)। – kobik
बस सोच रहा है: क्यों? डिफ़ॉल्ट व्यवहार में आपकी पसंद के अनुसार क्या नहीं है? –
@ मारजन वेनेमा हमारे डिजाइनर डी -5 के साथ XP में परीक्षण किए गए मालिक-ड्रा combobox – Andrew