Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

キャレット位置の文字情報をステータスバーに設定する際の再描画をまとめる #1601

Merged
merged 4 commits into from
Mar 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions sakura_core/apiwrap/CommonControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ namespace ApiWrap
{
return ::SendMessage( hwndStatus, SB_GETTEXTLENGTH, opt, (LPARAM)0 );
}
inline LRESULT StatusBar_GetRect(HWND hwndStatus, WPARAM opt, RECT* rect)
{
return ::SendMessage( hwndStatus, SB_GETRECT, opt, (LPARAM)rect );
}

inline int StatusBar_SetParts(HWND hwndCtl, int num, int* positions) { return (int)(DWORD)::SendMessage(hwndCtl, SB_SETPARTS, (WPARAM)num, (LPARAM)positions); }

Expand Down
32 changes: 23 additions & 9 deletions sakura_core/view/CCaret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,18 +844,32 @@ void CCaret::ShowCaretPosInfo()
}

auto& statusBar = m_pEditDoc->m_pcEditWnd->m_cStatusBar;

// SB_SETTEXT メッセージでステータスバーに文字列を設定する度に再描画が行われるのを防ぐ為に
// 設定時にパートのRECTを取得し最後にまとめて再描画を行う
HWND hWnd = statusBar.GetStatusHwnd();
RECT updatedRect = { 0 };
auto setStatusText = [&](int nIndex, int nOption, const WCHAR* pszText) {
bool ret = statusBar.SetStatusText(nIndex, nOption, pszText);
if (ret) {
RECT partRect;
StatusBar_GetRect(hWnd, nIndex, &partRect);
::UnionRect(&updatedRect, &updatedRect, &partRect);
}
};
::SendMessage(hWnd, WM_SETREDRAW, FALSE, 0);
if( m_bClearStatus ){
statusBar.SetStatusText( 0, SBT_NOBORDERS, L"" );
setStatusText( 0, SBT_NOBORDERS, L"" );
}
int nIndex = 1;
statusBar.SetStatusText( nIndex++, 0, szRowCol );
statusBar.SetStatusText( nIndex++, 0, szEolMode );
statusBar.SetStatusText( nIndex++, 0, szCaretChar );
statusBar.SetStatusText( nIndex++, 0, pszCodeName );
statusBar.SetStatusText( nIndex++, SBT_OWNERDRAW, L"" );
statusBar.SetStatusText( nIndex++, 0, szInsMode );
statusBar.SetStatusText( nIndex++, 0, szFontSize );
setStatusText( nIndex++, 0, szRowCol );
setStatusText( nIndex++, 0, szEolMode );
setStatusText( nIndex++, 0, szCaretChar );
setStatusText( nIndex++, 0, pszCodeName );
setStatusText( nIndex++, SBT_OWNERDRAW, L"" );
setStatusText( nIndex++, 0, szInsMode );
setStatusText( nIndex++, 0, szFontSize );
::SendMessage(hWnd, WM_SETREDRAW, TRUE, 0);
InvalidateRect(hWnd, &updatedRect, TRUE);
}
}

Expand Down
43 changes: 27 additions & 16 deletions sakura_core/window/CMainStatusBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ void CMainStatusBar::CreateStatusBar()
if( m_hwndStatusBar )return;

/* ステータスバー */
m_hwndStatusBar = ::CreateStatusWindow(
WS_CHILD/* | WS_VISIBLE*/ | WS_EX_RIGHT | SBARS_SIZEGRIP, // 2007.03.08 ryoji WS_VISIBLE 除去
L"",
m_hwndStatusBar = ::CreateWindowEx(
WS_EX_RIGHT | WS_EX_COMPOSITED,
STATUSCLASSNAME,
nullptr,
WS_CHILD/* | WS_VISIBLE*/ | SBARS_SIZEGRIP, // 2007.03.08 ryoji WS_VISIBLE 除去
0, 0, 0, 0, // X, Y, nWidth, nHeight
m_pOwner->GetHwnd(),
IDW_STATUSBAR
(HMENU)IDW_STATUSBAR,
CEditApp::getInstance()->GetAppInstance(),
nullptr
);

/* プログレスバー */
Expand Down Expand Up @@ -130,20 +135,21 @@ void CMainStatusBar::SendStatusMessage2( const WCHAR* msg )
@param pszText [in] 表示テキスト
@param textLen [in] 表示テキストの文字数
*/
void CMainStatusBar::SetStatusText(int nIndex, int nOption, const WCHAR* pszText, size_t textLen /* = SIZE_MAX */)
bool CMainStatusBar::SetStatusText(int nIndex, int nOption, const WCHAR* pszText, size_t textLen /* = SIZE_MAX */)
{
if( !m_hwndStatusBar ){
assert(m_hwndStatusBar != NULL);
return;
return false;
}
// StatusBar_SetText 関数を呼びだすかどうかを判定するラムダ式
// StatusBar_SetText 関数を呼びだすかどうかを判定する
// (StatusBar_SetText は SB_SETTEXT メッセージを SendMessage で送信する)
[&]() -> bool {
bool bDraw = true;
do {
// オーナードローの場合は SB_SETTEXT メッセージを無条件に発行するように判定
// 本来表示に変化が無い場合には呼び出さない方が表示のちらつきが減るので好ましいが
// 判定が難しいので諦める
if( nOption == SBT_OWNERDRAW ){
return true;
break;
}
// オーナードローではない場合で NULLの場合は空文字に置き換える
// NULL を渡しても問題が無いのかどうか公式ドキュメントに記載されていない
Expand All @@ -156,29 +162,34 @@ void CMainStatusBar::SetStatusText(int nIndex, int nOption, const WCHAR* pszText
LRESULT res = ::StatusBar_GetTextLength( m_hwndStatusBar, nIndex );
// 表示オペレーション値が変化する場合は SB_SETTEXT メッセージを発行
if( HIWORD(res) != nOption ){
return true;
break;
}
size_t prevTextLen = LOWORD(res);
WCHAR prev[1024];
// 設定済みの文字列長が長過ぎて取得できない場合は、SB_SETTEXT メッセージを発行
if( prevTextLen >= _countof(prev) ){
return true;
break;
}
// 設定する文字列長パラメータが SIZE_MAX(引数のデフォルト値)な場合は文字列長を取得
if( textLen == SIZE_MAX ){
textLen = wcslen(pszText);
}
// 設定済みの文字列長と設定する文字列長が異なる場合は、SB_SETTEXT メッセージを発行
if( prevTextLen != textLen ){
return true;
break;
}
if( prevTextLen > 0 ){
::StatusBar_GetText( m_hwndStatusBar, nIndex, prev );
// 設定済みの文字列と設定する文字列を比較して異なる場合は、SB_SETTEXT メッセージを発行
return (wcscmp(prev, pszText) != 0);
bDraw = wcscmp(prev, pszText) != 0;
}
else{
return true;
else {
// 設定する文字列長が0の場合は設定する文字列長が0より大きい場合のみ設定する(既に空文字なら空文字を設定する必要は無い為)
bDraw = textLen > 0;
}
}() ? StatusBar_SetText( m_hwndStatusBar, nIndex | nOption, pszText ) : 0;
}while (false);
if (bDraw) {
StatusBar_SetText(m_hwndStatusBar, nIndex | nOption, pszText);
}
return bDraw;
}
2 changes: 1 addition & 1 deletion sakura_core/window/CMainStatusBar.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class CMainStatusBar : public CDocListenerEx{
HWND GetProgressHwnd() const{ return m_hwndProgressBar; }

//設定
void SetStatusText(int nIndex, int nOption, const WCHAR* pszText, size_t textLen = SIZE_MAX);
bool SetStatusText(int nIndex, int nOption, const WCHAR* pszText, size_t textLen = SIZE_MAX);
private:
CEditWnd* m_pOwner;
HWND m_hwndStatusBar;
Expand Down