2017-07-19 34 views
0

我已經實現了基於API文檔的自定義wxOwnerDrawnComboBox。然後,我將它放在wxPanel上,然後使用SetPopupMaxHeight限制組合彈出窗口一次只顯示3個項目。但彈出式窗口在彈出式窗口的底部顯示了一個額外的白色行。OSX上的wxOwnerDrawnComboBox在滾動底部有一個額外的行

下面是截圖(我實現它的minimal_cocoa樣本項目):
pic1pic2

如圖所示,只有6個項目,但在「第5項」的結尾,有一個額外的行。

在這個問題上的一些注意事項:

  • 它始終是默認的白色
  • 它只使用時發生(通過自定義 其他行黑色的BG選中)SetPopupMaxHeight
  • 它發生在Mac上(即在Windows上沒有問題)
  • 點擊額外的行將關閉彈出窗口(所以我想它是繪製的部分彈出窗口)

下面是代碼(簡化爲minimal_cocoa項目):


// CUSTOM CLASS DECLARATION 

class MyOwnerDrawnComboBox : public wxOwnerDrawnComboBox 
{ 
public: 
    static int getItemHeight() 
    { 
     return 25; 
    } 

public: 
    // ctor 

    MyOwnerDrawnComboBox(wxWindow* parent, 
         const wxPoint& pos = wxDefaultPosition, 
         const wxSize& size = wxDefaultSize, 
         int n = 0, 
         const wxString choices[] = NULL, 
         long style = wxODCB_STD_CONTROL_PAINT) 
    : wxOwnerDrawnComboBox(parent, 
          wxID_ANY, 
          wxEmptyString, 
          pos, 
          size, 
          n, 
          choices, 
          style, 
          wxDefaultValidator, 
          "MyOwnerDrawnComboBox") 
    { 
    } 

    // overrides 

    virtual void OnDrawItem (wxDC& dc, const wxRect& rect, int item, int flags) const 
    { 
     dc.SetTextForeground(*wxRED); 

     // for debugging purposes, display the item index instead 
     wxString label = wxString::Format("item %d", item); 
     dc.DrawLabel(label, rect, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); 
    } 

    virtual wxCoord OnMeasureItem (size_t item) const 
    { 
     return 25; 
    } 

    virtual wxCoord OnMeasureItemWidth (size_t item) const 
    { 
     return -1; // use default 
    } 
}; 

// CUSTOM CLASS USAGE 

wxPanel* panel = new wxPanel(this, wxID_ANY); 
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); 
wxString items[] = {"1", "2", "3", "4", "5", "6"}; // unused 
MyOwnerDrawnComboBox* odcb = new MyOwnerDrawnComboBox(panel, 
                 wxDefaultPosition, 
                 wxSize(150, 30), 
                 6, 
                 items); 
odcb->SetPopupMaxHeight(3 * MyOwnerDrawnComboBox::getItemHeight()); 
sizer->Add(odcb, 0, wxALL, 10); 
sizer->Layout(); 
panel->SetSizer(sizer); 

我試過幾件事情:

  1. 使用的默認OnDrawItem方法(同一問題)
  2. 檢查是否需要撥打OnDrawItem(沒有額外的呼叫)
  3. 調整返回的項目高度OnMeasureHeight(同樣的問題)
  4. 經過對樣品/組合/ combo.cpp樣的行爲(同樣的問題)

    combo-cocoa-1combo-cocoa-2


在我的wxWidgets的一些信息建設:

  • 直接從他們的github回購
  • 進行任何更改到wxWidgets源除了在設置定義wxUSE_XTEST 1克隆它。^ h
    • 我檢查和wxUSE_ODCOMBOBOXwxUSE_COMBOCTRL#define倒是
  • 使用下列選項../configure
    • --with-osx_cocoa
    • --with-macosx-version-min=10.7
    • --with-macosx-sdk=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk
    • --enable-debug
    • --disable-shared
    • --enable-unicode
    • --prefix="$(pwd)"

我ENV一些信息:

  • MacOS的10.12.5(塞拉利昂)
  • 的Xcode 8.3.3(8E3004b)
  • minimal_cocoa顯示的wxWidgets 3.1.1

有沒有人遇到過這個問題?
我現在正在通過不再使用SetPopupMaxHeight來解決這個問題。

如果有人有解決方案,儘管分享。

+0

你嘗試過組合樣本嗎?它的行爲是否一樣? – Igor

+0

@Igor是的,我試過了。所有的組合實現都有相同的問題,無論是odcb還是帶有自定義ComboPopup的ComboCtrl(我編輯帖子以添加屏幕截圖)。 –

+0

你是如何配置圖書館的?當你嘗試這個樣本時 - 你是否以任何方式改變它?構建過程中是否收到任何警告? – Igor

回答

0

我通過對wx源文件進行一些更改來修復它。

的src /通用/ vscroll.cpp

wxVarScrollHelperBase::DoScrollToUnit

// determine the real first unit to scroll to: we shouldn't scroll beyond 
// the end 
size_t unitFirstLast = FindFirstVisibleFromLast(m_unitMax - 1, true); 
if (unit > unitFirstLast) 
    unit = unitFirstLast; 

通行證false而不是FindFirstVisibleFromLast

這將允許該方法考慮一個項目作爲第一個項目,即使最後一個項目只是部分可見(這裏的「部分」,根據我的測試,真的很像「幾乎完全可見」,只有約〜 2pts被隱藏)。通過true,滾動向下移動到下一個項目,從而添加額外的行。

的src /通用/ odcombo.cpp

wxVListBoxComboPopup::OnMouseMove

 // Only change selection if item is fully visible 
     if ((y + fromBottom) >= 0) 
     { 
      wxVListBox::SetSelection((int)line); 
      return; 
     } 

爲了配合2點邊界在wxVListBoxComboPopup::GetAdjustedSize正在考慮,我改變了IF條件(y + fromBottom + 2)以允許通過移動鼠標滾動窗口中的最後一項,儘管它不完全可見。

的src /通用/ vlbox.cpp

else // line is at least partly visible 
    { 
     // it is, indeed, only partly visible, so scroll it into view to 
     // make it entirely visible 
     // BUT scrolling down when m_current is first visible makes it 
     // completely hidden, so that is even worse 
     while ((size_t)m_current + 1 == GetVisibleRowsEnd() && 
       (size_t)m_current != GetVisibleRowsBegin() && 
       ScrollToRow(GetVisibleBegin() + 1)) ; 

註釋出的是,儘管環禁用自動滾動當鼠標指針懸停在部分可見項目。