Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Как усечь слева подкаталоги?


Автор: andrew_121 14.5.2009, 14:18
Дарова!
Собственно это и есть вопрос.
Заранее спасибо!

Автор: GremlinProg 14.5.2009, 17:44
о чем вопрос-то?

какие подкаталоги,
почему слева,
и при чем тут строка?

так топик ни кто не поймет, объяснять надо, andrew_121!

Автор: andrew_121 14.5.2009, 18:08
На форме есть Static, в него вписывается путь к каталогу. Так вот когда вписываю строку длинее чем вмещается, хотелось бы ее минимизировать, усекая часть пути, и заменяя ее точками.
Все не раз видели такое.

Сорри за первый пост.

Автор: SenkraD 14.5.2009, 19:08
andrew_121, ну как я понял со стоками мы работать умеет,
так что проблемма в том чтобы получить длину строки в пикселях?
Если мо предположение правильные то 
Код

// its pseudo code - i haven't win machine under hands

std::string  path      = getPath();
HDC          ctrlDC    = staticCTRL.getDC();
size_t const kCtrlLen  = staticCtrl.getLen();
SIZE         textSize  = { 0 };

do
{
     GetTextExtentPoint32(ctrlDC, path.c_str(), path.size(), &textSize);
     if (kCtrlLen < textSize.cx)
     {
           path = removePathComponentsFromPathFromMiddle(path, kComponentCount);
     }
} while (kCtrlLen < textSize.cx);
staticCtrl.setText(path);

Автор: dumb 14.5.2009, 19:17
http://msdn.microsoft.com/en-us/library/dd162498(VS.85).aspx + DT_PATH_ELLIPSIS

Автор: andrew_121 14.5.2009, 19:28
Цитата(SenkraD @  14.5.2009,  19:08 Найти цитируемый пост)
HDC          ctrlDC    = staticCTRL.getDC();

Гы... ) А как у Static-а, созданого средствами WinAPI получить сие?

Автор: GremlinProg 14.5.2009, 19:35
то, что все не раз видели, это скорее PathCompactPath из shlwapi:
Код

BOOL PathCompactPath(
    HDC hDC,
    LPTSTR lpszPath,
    UINT dx
);

Автор: andrew_121 15.5.2009, 16:38
А как у Static-а, созданого средствами WinAPI получить HDC ?

Автор: GremlinProg 15.5.2009, 16:54
Цитата(andrew_121 @  15.5.2009,  18:38 Найти цитируемый пост)
А как у Static-а, созданого средствами WinAPI получить HDC ?

Код

hdc = ::GetDC(hwndStatic);
::PathCompactPath(...);
::ReleaseDC(hwndStatic,hdc);


Автор: andrew_121 15.5.2009, 17:08
GremlinProg, Спасибо!

Автор: artsb 15.5.2009, 17:17
andrew_121, тебе же dumb написал про DrawText. Чего ты паришься?  smile 
Или ты любишь поизвращаться  smile 

Автор: andrew_121 15.5.2009, 17:40
artsb, 
Код

int DrawText(
  __in     HDC hDC,
  __inout  LPCTSTR lpchText,
  __in     int nCount,
  __inout  LPRECT lpRect,
  __in     UINT uFormat
);

Так тут и нужен HDC. smile 

Автор: artsb 15.5.2009, 18:02
Цитата(andrew_121 @  15.5.2009,  17:40 Найти цитируемый пост)
Так тут и нужен HDC. 

В качестве первого параметра можно передать хедл любого канваса. А в данном случае вроде можно просто передать NULL, т.к. от него всё равно толку нет  smile

Добавлено @ 18:13
На счёт NULL я погорячился smile
Ещё нужен флаг DT_MODIFYSTRING:
Код

AnsiString asText = Edit1->Text;
TRect R = StaticText1->BoundsRect;
DrawText(this->Canvas->Handle, asText.c_str(), -1, &R, DT_MODIFYSTRING | DT_PATH_ELLIPSIS);
StaticText1->Caption = asText;

тогда в asText будет хранить изменённая строка.  smile 

Единственно (только сейчас заметил), строка будет иметь вид:
Цитата

C:\WINDOWS\system32\w...\myfile.ini

 :(

Похоже, придётся поизвращаться smile

Автор: GremlinProg 15.5.2009, 18:39
Цитата(artsb @  15.5.2009,  20:02 Найти цитируемый пост)
В качестве первого параметра можно передать хедл любого канваса.

конечно можно, но статику, как и любым другим контролам можно выставить шрифт, отличающийся от встроенного
в таком случае, как DrawText с DT_PATH_ELLIPSIS, так и PathCompactPath правильных габаритов текста для этого статика уже не посчитают, т.е. будут либо обрезать строку там, где ее обрезать не нужно, либо обрезать за габаритами, в зависимотси от разницы ширин текста на этих девайсах

Автор: artsb 15.5.2009, 18:56
Цитата(GremlinProg @  15.5.2009,  18:39 Найти цитируемый пост)
конечно можно, но статику, как и любым другим контролам можно выставить шрифт, отличающийся от встроенного
в таком случае, как DrawText с DT_PATH_ELLIPSIS, так и PathCompactPath правильных габаритов текста для этого статика уже не посчитают, т.е. будут либо обрезать строку там, где ее обрезать не нужно, либо обрезать за габаритами, в зависимотси от разницы ширин текста на этих девайсах 

Об этом я не подумал. Спасибо GremlinProg.

Добавлено через 2 минуты и 28 секунд
Хотя погоди. DrawText просит канву, на которой собирается рисовать. Скорее всего она учитывает шрифт...

Автор: GremlinProg 15.5.2009, 19:00
по крайней мере, можно просто учесть шрифт:
Код

...
hOldFont   = ::GetCurrentObject(hdc,OBJ_FONT);
hFont = (HFONT)::SendMessage(hwndStatic,WM_GETFONT);
::SelectObject(hdc,hFont);
// ...использовать hdc...
::SelectObject(hdc,hOldFont);
...

тогда пойдет любой HDC, хоть десктопа: GetDC(HWND_DESKTOP)

Добавлено через 3 минуты и 49 секунд
Цитата(artsb @  15.5.2009,  20:56 Найти цитируемый пост)
Скорее всего она учитывает шрифт...

да нет, ей в принципе без разницы на чем рисовать
шрифт с окна функции GDI сами не устанавливают,
иначе мы не могли бы его сменить, кроме как явной посылкой WM_SETFONT

Автор: artsb 15.5.2009, 19:11
Вот:
Код

AnsiString EllipsisPath(const AnsiString &asString, TFont *fParentFont, int iParentWidth, TCanvas *cCanvas)
{
AnsiString asNewString = asString;
TFont *fTempFont = cCanvas->Font;
cCanvas->Font->Assign(fParentFont);
if(iParentWidth < cCanvas->TextWidth(asNewString))
{
  while(iParentWidth < cCanvas->TextWidth("..." + asNewString))
    asNewString.Delete(1, 1);
  asNewString = "..." + asNewString;
}
cCanvas->Font->Assign(fTempFont);
return asNewString;
}

// юзать можно так
StaticText1->Caption = EllipsisPath(Edit1->Text, StaticText1->Font, StaticText1->BoundsRect.Width(), this->Canvas);

Конечно можно было создать объект канвы в функции и юзать его, но это же время и ресурсы smile

ЗЫ не смотря на то, что это изврат, не бейте сильно smile

Автор: GremlinProg 15.5.2009, 19:17
Цитата(artsb @  15.5.2009,  21:11 Найти цитируемый пост)

while(iParentWidth < cCanvas->TextWidth("..." + asNewString))
    asNewString.Delete(1, 1);
    asNewString = "..." + asNewString;

это делает DrawText с флагом DT_END_ELLIPSIS или пословно, с флагом DT_WORD_ELLIPSIS
только не "три точки", а "троеточие", одним символом

Добавлено через 1 минуту и 59 секунд
а, ну да, не заметил, не последние, а первые символы
но в любом случае, это не задача топика

Автор: artsb 15.5.2009, 19:44
Цитата(GremlinProg @  15.5.2009,  19:17 Найти цитируемый пост)
это не задача топика 

Цитата

Как усечь слева подкаталоги? Если строка не вмещается.

Или я не правильно понял?

Автор: GremlinProg 15.5.2009, 21:31
Цитата(artsb @  15.5.2009,  21:44 Найти цитируемый пост)
Или я не правильно понял?

Цитата(artsb @  15.5.2009,  21:44 Найти цитируемый пост)
Как усечь слева подкаталоги? Если строка не вмещается.

не символы, а подкаталоги:
Код

С:\усеченный\...\путь\до\файла

два варианта уже предложены

Автор: artsb 15.5.2009, 23:18
Изначально я думал, что нужно получить строку вида:
Код

...\путь\до\файла

Если это так, то ничего не мешает добавить в моей функции пару строк: smile
Код

AnsiString EllipsisPath(const AnsiString &asString, TFont *fParentFont, int iParentWidth, TCanvas *cCanvas)
{
AnsiString asNewString = asString;
TFont *fTempFont = cCanvas->Font;
cCanvas->Font->Assign(fParentFont);
if(iParentWidth < cCanvas->TextWidth(asNewString))
{
  while(iParentWidth < cCanvas->TextWidth("..." + asNewString))
    asNewString.Delete(1, 1);
  int iPos = asNewString.Pos("\\");
  if(iPos)
    asNewString.Delete(1, iPos - 1);
  else if((iPos = asNewString.Pos("/")))
    asNewString.Delete(1, iPos - 1);
  asNewString = "..." + asNewString;
}
cCanvas->Font->Assign(fTempFont);
return asNewString;
}


Если же нужен такой вариант как написал GremlinProg, то как мне кажется, DrawText будет в самый раз  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)