fc2ブログ

自作PathCompactPath

Win32APIのPathCompactPathは長いファイル名を表示する際に表示領域から
はみ出してしまった分を...に置き換えて省略してくれる便利なAPIですが
SHLWAPI.DLLに実装されているのでIEが古いと使えません。
そこで自作して同じ機能の物を作成。

これ、実は結構簡単。キモはDrawTextEx。
引数にDT_PATH_ELLIPSISとDT_MODIFYSTRINGとDT_CALCRECTを指定すると
省略されたパスを取得できます。
DT_PATH_ELLIPSISはパスを省略させるフラグで
DT_MODIFYSTRINGは省略されたパスを保存するフラグで
DT_CALCRECTは描写を抑えるフラグになります。
これを組み合わせる事で省略されたパスを取得できます。

なぜDrawTextでは無くDrawTextExなのかというと
DrawTextの2番目の引数に変換するパスを渡す訳ですが
これLPCTSTR、つまりconst指定なので本来ならココに指定したバッファは
変更されてはいけないはずなんです。でも無理矢理変換してしまうようですが。
# これは完全に実装ミスだよなぁ。
それがDrawTextExだとconst指定ではないので安心です。

それを踏まえてコードを書くと以下のような感じです。
BOOL MyPathCompactPath(HDC hDC, LPTSTR lpszPath, UINT dx)
{
int nRes;
RECT rc = { 0, 0, dx, 0 };
nRes = ::DrawTextEx(hDC, lpszPath, -1, &rc,
DT_PATH_ELLIPSIS |
DT_MODIFYSTRING |
DT_CALCRECT, NULL);
return (nRes != 0);
}

 
オマケでPathSetDlgItemPathの代用
bool MyPathSetDlgItemPath(HWND hDlg, int id, LPCSTR pszPath)
{
char* lpsz = new char[::lstrlen(pszPath) + 4];
::lstrcpy(lpsz, pszPath);
HWND hItemWnd = ::GetDlgItem(hDlg, id);
HDC hDC = ::GetDC(hItemWnd);
HGDIOBJ hFont = (HGDIOBJ)::SendMessage(hItemWnd, WM_GETFONT,
0, 0);
HGDIOBJ hOldFont = ::SelectObject(hDC, hFont);
RECT rc;
int nRes;
::GetClientRect(hItemWnd, &rc);
nRes = ::DrawTextEx(hDC, lpsz, -1, &rc,
DT_PATH_ELLIPSIS |
DT_MODIFYSTRING |
DT_CALCRECT, NULL);
::SelectObject(hDC, hOldFont);

::ReleaseDC(hItemWnd, hDC);
::SetWindowText(hItemWnd, lpsz);
delete [] lpsz;
return (nRes != 0);
}

ポイントとしてデバイスコンテキストにきちんとフォントを設定してやらないと
きちんとコントロールに収まらないのでその辺を処理してます。
それからDrawTextExでDT_PATH_ELLIPSISフラグを設定すると
最大で4バイト長くなる場合が有るのでそのぶん多く確保してます。

コメントの投稿

非公開コメント

月別アーカイブ
カテゴリー
リンク
ブログ内検索
RSSフィード