2012-01-12 6 views
1

私は、AWTとほぼ同じクラスリストとプログラミング構造を持つことになっているATLに基づいて、私自身のプライベートWindowsデスクトップアプリケーションのユーザーインターフェイスフレームワークに取り組んでいます。 (私はC#を使用している場合は、ほとんどすべての以前のGUI開発をWTLまたはWinFormsで行っています)文字列を追加した後でオーナー以外の描画したリストボックスに描画の問題があるのはなぜですか?

リストボックスクラスに関しては問題があります。他のすべてのコントロールは、WM_PAINTに関与することなく、正しく再描画できます。リストボックス?そうではありません。ここではそれがどのように見えるかです:

  • Normal
  • After moving < - 下部にある赤いマークを無視します。私は間違ってスクリーンショットを描き、それを捕まえなかった。

実際の問題がどこで発生しているのかわからないので、私が考えることができる描画のすべてのコードはここにあります。 他のソースコードが役に立ったら、私に知らせてください。ここで

はWM_CTLCOLORLISTBOXハンドラのための私のコードです:

virtual LRESULT WmCtlColorListbox(MSG& msg, bool& handled) 
    { 
     handled = true; 
     return colorControl(msg.message, reinterpret_cast<HDC>(msg.wParam), reinterpret_cast<HWND>(msg.lParam)); 
    } 

LRESULT colorControl(UINT origMsg, HDC hdc, HWND window) 
    { 
     if (window == *this) 
     { 
      ::SetBkMode(hdc, _backMode); 
      ::SetBkColor(hdc, _backColor); 
      ::SetTextColor(hdc, _foreColor); 
      return (LRESULT) _backBrush; 
     } 

     return ::SendMessage(window, origMsg, reinterpret_cast<WPARAM>(hdc), reinterpret_cast<LPARAM>(window)); 
    } 

WM_PAINTハンドラ:

inline virtual LRESULT WmPaint(MSG& msg, bool& handled) 
{ 
    OnPaint(handled); 
    return handled ? 0 : 1; 
} 

inline virtual void OnPaint(bool& handled) { } 

WM_ERASEBKGNDハンドラ:

virtual LRESULT WmEraseBkgnd(MSG& msg, bool& handled) 
{ 
    HDC hdcWindow = (HDC)msg.wParam; 
    RECT r; 
    this->GetWindowRect(&r); 
    ::FillRect(hdcWindow, &r, _backBrush); 
    this->Invalidate(FALSE); 
    handled = true; 
    return 1; 
} 

直前に呼び出される仮想関数ATLはクラスを登録します:

virtual void OnRegistering(CreationParameters& createParams) 
{ 
    createParams.BaseClassName = WC_LISTBOX; 
    createParams.WindowExStyles |= WS_EX_CLIENTEDGE; 
} 

I 使用にはのOnPaint内でこのコードを持っている:

PAINTSTRUCT ps; 
HDC hdcWindow = this->BeginPaint(&ps); 

// This class automatically handles the background 
// drawing for any other window 
if (_backBrush == NULL) 
    _backBrush = ::CreateSolidBrush(_backColor); 

::FillRect(hdcWindow, &ps.rcPaint, _backBrush); 
this->EndPaint(&ps); 

が、テキストのどれも現れないだろう、おそらくテキストが自動的に描画された後にWM_PAINTが呼ばれたので...

説明のビット:

CreationParametersは適切なCWndClassInfoに変換され、RegisterはOnReの後に呼び出されますgisteringメソッドは終了します。

  • _backModeは、ベースの「ウィンドウ」クラスのプライベートメンバーであり、TRANSPARENTまたはOPAQUEです。リストボックスの場合、現在OPAQUEにハードコーディングされています
  • _backColorと_foreColorはプライベートCOLORREFメンバーです。
  • _backBrushは、単純に_backColorのブラシで、コントロールクラスが分解されたときに破棄されるプライベートHBRUSHです。

WM_PAINTハンドラは、単にイベントアクティベータ(OnPaint)を呼び出すだけで、何もしません。 WM_PAINTハンドラは、handlesがfalseの場合、DefWindowProcを呼び出します。

私はWC_LISTBOXを手作業でスーパークラス化し、それらの値を恐ろしい結果でORして、作成前にクラススタイルでCS_HREDRAWとCS_VREDRAWを使いこなしました(リストボックスに追加されたテキストが返されても表示されない適切な数の項目を返すLB_GETCOUNTでは、リストボックスはにすべてを再描画しないので、私はアイデアがありません。

誰もこれの前に何かを見たことがありますか、私は何かが紛失している(または私はどのようなウィンドウメッセージを処理するはずです)教えてもらえますか?

+1

ここでは暗闇の中を覗いていますが、NULL_BRUSHで編集ボックスを塗りつぶすときに、同様の背景が覚えています。たぶんCreateSolidBrushはどこかでNULLを返します。また、なぜWM_ERASEBACKGROUNDのウィンドウを検証するのですか? – pezcode

+0

問題のPARTを解決しました。_backBrushは、* _backColorが既に設定されているものと異なるものに割り当てられている場合にのみ、NULLのためにチェックされました。これを修正しました。 http://i.imgur.com/ix1gM.png – jvstech

+0

@pezcode: 'NULL_BRUSH'は' NULL'と同等ではありません。 –

答えて

4

座標が一致しないWmEraseBkgndです。 GetWindowRectは画面座標を与え、FillRectはローカル座標を使用します。 GetClientRectを使用するか、左上と右下隅をScreenToClientと変換する必要があります。

+0

Egad、ありがとう。私はそれを捕まえなかったとは信じられません。ウィンドウがトップレベルかどうかによってGetClientRectまたはGetWindowRectを呼び出すgetMappedRectという関数があります。私はそれを交換するのを忘れていたと思う。 – jvstech

関連する問題