2017-09-19 1 views
0

以下のコードを使用して、WindowsのListViewヘッダーコントロールをサブクラス化します。私の手続きはうまくいき、ヘッダーコントロール上でマウスのホバーにうまく反応します。Ownerdrawn Listviewヘッダー行をすぐに表示する方法

私の問題は、私が「初めて」大きなリストを作成するときに、リストがフル装備になるまで、ヘッダ行は表示されませんです。

Header line during loading big list 1st time

その後、私は開かれたリストを削除する場合そして新しいもの、または同じ古いものを作成し、ヘッダ行はリストが完了するのを待っていない、すぐに示しています

Header line during loading big list 2nd time

私はヘッダーコントロールをサブクラス化していない場合は、ネイティブW indowsプロシージャは、リストが完了するのを待たずに、ただちにヘッダー行を表示しますが、カスタマイズを失います。

ヘッダー行がすぐに表示されるようにするには、何が欠けているのですか?

注:

私が開始する前に、リストビュー項目を追加し終えた後LockWindowUpdate()を呼び出します。私はLockWindowUpdate()に電話をかけようとしませんでしたが、結果はヘッダー行がすべての項目を追加し終わっても表示されませんでした。ヘッダー行にマウスを移動して新しいWM_PAINT msgを強制するまで待ちます。ここで

は、私のサブクラスの機能である:

static char* HeaderText[20] = {"A","B","C","D","E","F","G","H","I","J", 
           "K","L","M","N","O","P","Q","R","S","T"} ; 


LRESULT APIENTRY HeaderSubclassProc (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)       
{ 
static int  y ; 
static int  xe ; 
static int  xr ; 
static int  HBtn = -1 ; 
static RECT Hrc ; 
static HPEN Pen ; 
static HPEN HPen ; 
static HBRUSH Brush ; 
static HBRUSH HBrush ; 
static TRACKMOUSEEVENT tme = {sizeof (TRACKMOUSEEVENT),TME_LEAVE,NULL, 
           HOVER_DEFAULT} ; 
HDC  hDC ; 

switch (msg) { 
    RECT rc ; 

    case IDM_INIT : 
     Pen = CreatePen (PS_SOLID,0,0xF2F2F2) ; 
     HPen = CreatePen (PS_SOLID,0,0xF88420) ; 
     Brush = CreateSolidBrush (0xD2D2D2) ; 
     HBrush = CreateSolidBrush (0xFFEFE0) ; 
     Header_GetItemRect (hwnd,19,&rc) ; 
     xr = rc.right ; 
     tme.hwndTrack = hwnd ; 
     return 0 ; 

    case WM_CLOSE : 
     DeleteObject (Pen) ; 
     DeleteObject (HPen) ; 
     DeleteObject (Brush) ; 
     DeleteObject (HBrush) ; 
     return 0 ; 

    case WM_SIZE : 
     TEXTMETRIC tm ; 
     hDC = GetDC (hwnd) ; 
     GetTextMetrics (hDC,&tm) ; 
     ReleaseDC (hwnd,hDC) ; 
     Header_GetItemRect (hwnd,0,&rc) ; 
     y = (rc.bottom - rc.top - tm.tmHeight)/2 + tm.tmAscent ; 
     xe = LOWORD (lParam) ; 
     break ; 

    case WM_MOUSELEAVE : 
     HBtn = -1 ; 
     InvalidateRect (hwnd,&Hrc,true) ; 
     return 0 ; 

    case WM_MOUSEMOVE : 
     int x ; 
     x = LOWORD (lParam) ; 
     if (HBtn > -1 && x > xr) { 
      HBtn = -1 ; 
      InvalidateRect (hwnd,&Hrc,true) ; 
      break ; 
     } /* if (HLBtn == 19 && x > xr) */ 
     for (int Btn = 0 ; Btn < 20 ; Btn++) { 
      Header_GetItemRect (hwnd,Btn,&rc) ; 
      if (x > rc.left && x < rc.right) { 
       if (Btn == HBtn) 
        break ; 
       HBtn = Btn ; 
       Hrc = rc ; 
       InvalidateRect (hwnd,NULL,true) ; 
       break ; 
      } /* if (x > rc.left && x < rc.right) */ 
     } /* for (int Btn = 0 ; Btn < 20 ; Btn++) */ 
     TrackMouseEvent (&tme) ; 
     break ; 

    case WM_PAINT : 
     PAINTSTRUCT ps ; 
     hDC = BeginPaint (hwnd,&ps) ; 
     int DefDC = SaveDC (hDC) ; 

     SelectObject (hDC,Pen) ; 
     SelectObject (hDC,Brush) ; 
     SetTextAlign (hDC,TA_BASELINE | TA_CENTER) ; 
     SetBkMode (hDC,TRANSPARENT) ; 

     for (int Btn = 0 ; Btn < 20 ; Btn++) { 
      if (Btn == HBtn) 
       continue ; 
      Header_GetItemRect (hwnd,Btn,&rc) ; 
      int x = (rc.right + rc.left)/2 ; 
      Rectangle (hDC,rc.left,rc.top,rc.right + 1,rc.bottom) ; 
      ExtTextOut (hDC,x,y,ETO_NUMERICSLATIN,&rc,HeaderText[Btn], 
          (UINT) strlen (HeaderText[Btn]),NULL) ; 
     } /* for (int Btn = 0 ; Btn < 20 ; Btn++) */ 
     Rectangle (hDC,rc.right,rc.top,xe,rc.bottom) ; 

     if (HBtn > -1) { 
      Header_GetItemRect (hwnd,HBtn,&rc) ; 
      x = (rc.right + rc.left)/2 ; 
      SelectObject (hDC,HPen) ; 
      SelectObject (hDC,HBrush) ; 
      Rectangle (hDC,rc.left + 1,rc.top + 1,rc.right,rc.bottom - 1) ; 
      ExtTextOut (hDC,x,y,ETO_NUMERICSLATIN,&rc,HeaderText[HBtn], 
          (UINT) strlen (HeaderText[HBtn]),NULL) ; 
     } /* if (HLBtn > -1) */ 

     RestoreDC (hDC,DefDC) ; 
     EndPaint (hwnd,&ps) ; 
     return 0 ; 

} /* switch (msg) */ 

return CallWindowProc ((WNDPROC) DefaultHeaderProc,hwnd,msg,wParam,lParam) ; 

} /* HeaderSubclassProc */ 
+0

多分あなたは何とかリストを無効にする必要がありますか? – VuVirt

答えて

2

あなたは間違いなくすべてのLockWindowUpdate()を使用されるべきではない(理由を説明Raymond Chen's blog上の多数の記事があります)。

正しい解決策は、あなたの更新を完了するまで、その後、その描画を無効に図面を再度有効に、そして最終的にInvalidateRect()/UpdateWindow()、またはRedrawWindow()との再描画をトリガするために再びWM_SETREDRAWを送信するために、リストビューにWM_SETREDRAWメッセージを送信することです。

use the ListView in virtual mode特に、多くのアイテムを表示する場合は、use the ListView in virtual modeです。

+0

私はWM_SETREDRAWを試しましたが、問題は解決しません。ここでも、ネイティブWindowsヘッダープロシージャーでは機能しますが、サブクラス化ヘッダーでは機能しません。リストを完成させた後、プログラムでヘッダを再描画できないので、問題がさらに悪化することもあります。 InvalidateRect()/ UpdateWindow()とRedrawWindow()はヘッダーを表示できませんでした。私は手動でヘッダーを表示するためにウィンドウをカバー/アンカバーする必要があります。 WM_PAINTのサブクラス処理で何かが見当たりませんが、それを理解することはできません。 – makhlouf

+0

ListViewのヘッダーをどのようにサブクラス化するか、またはListViewアイテムをどのように埋め込むかについては説明していません。 –

関連する問題