Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

fit a long filename into a small label

Status
Not open for further replies.

hennep

Programmer
Dec 10, 2000
429
0
16
How can I make this VB code work in CBuilder:

Dim BoundingRect As RECT
Dim TempDC As Long
Dim strText As String
GetClientRect Text1.hwnd, BoundingRect
TempDC = CreateCompatibleDC(Form1.hdc)
strText = "C:\This\Is\A\Long\String\To\A\File.Name"
DrawText TempDC, strText, Len(strText), BoundingRect, DT_PATH_ELLIPSIS_MODIFY
Text1.Text = strText
DeleteDC TempDC

I already tried to convert it myself but I get to many errors that I don't understand.

I want to fit a long file name into the caption of a label.

This name: "C:\This\Is\A\Long\String\To\A\File.Name"
should to convert to something similar to this:
"C:\This\Is\...\A\File.Name"
But only when the label is too small to hold the complete file name.


 
This piece of code nearly does what I want.

RECT BoundingRect = { 0, 0, Label1->Width, Label1->Height };
Label1->Caption = "C:\\This\\Is\\A\\Long\\String\\To\\A\\File.Name";
char *p = Label1->Caption.c_str();
HANDLE TempDC = CreateCompatibleDC( this->GetDeviceContext(this->Handle) );
DrawText( TempDC, p, strlen(p), &BoundingRect, DT_PATH_ELLIPSIS + DT_MODIFYSTRING );
Label1->Caption = p;
DeleteDC( TempDC );

It leaves a to much space on the right, who can explain this effect ?
 
Hi hennep

You can use the BCB function MinimizeName(),

Set the AutoSize property of the Label to false.

Add this to the include section
#include <FileCtrl.hpp>

AnsiString FileName = &quot;C:\\A\\Very\\Long\\Path\\To\\A\\File.tst&quot;;
Label1->Caption = MinimizeName(FileName,Label1->Canvas, Label1->Width);
 
thanks BTecho,

Your code &quot;nearly&quot; shows the right string.
A filename ending on &quot;S.TXT&quot; shows up to half the S, the end part is missing.
Try changing the width of the label, sometimes the string fits, sometimes it doesn't.

We have probably found the reason why Micro$oft API's use some extra space at the end of the label :)


 
The process of parsing a string to divide, search, display
certain parts or sections can be accomplished by using the string functions such as strcmp, strcat,strcpy, etc...

you set the rules and process the text. I have written several parsing functions, to convert long file names to dos 8/3 filname, and to create a search function to search for a string in a line of text, among others. The process begins by setting the rules for how you want your result to look. such as

1. if the file name is x long copy the characters up to and including the last &quot;\&quot; that occur before the n'th character.

the above rule will handle the the first part of the truncated file name. copy this to &quot;buff1 [256]&quot; and strcat the &quot;...&quot; string. then you create a rule to process the last part. some things that you probably were not aware of
will become apparent that apply to strings and there structure. be wary of one off errors. if the results are not what you expect, increment or decrement the counters and retest. Im sure that some will say that you are wasting your time reinventing the wheel when they can probably point you to some fancy function but then what have you learned. The wheel must be reinvented occasionally otherwise we would still be pushing our fred flinstone mobile into the driveway.

madhatter@tomcruz.net
 
hi butthead,

When I wrote the code I posted on Jan, 11th I thought I was reinventing the wheel. Maybe I can make it look better using the string functions but I dont want to spend that much time.
I still hope there is a function or api that can devide the remaining characters on the label without wasting space or cutting off text on the right.
With just string functions I cannot make it fit into a Label. I also need a function that calculates the occupied space taking into account the font, fontsize etc. The only one I have found so far is DrawText.
 
The following function changes a long file name to the dos 8/3 standard.

not complicated and if you wait for the api you probably missed a chance to do some unique code.

copy and paste and send it a string by reference.
The code below probably could be tweeked to do what you want. you can display any string in the label.

char string [] = &quot;string&quot;;
label1->Text = string;
and size of should give you the size of the label afterwards.

if you give up before you try you will never do anything.
and I bet you could write the code in less time than you think. Probably before the gurus send you the cool api function.

void path_dos_check (char *buff)
{
int x = strlen (buff);

// The section counter. The position of the last '\'.
int z = 2;

for (int y = 3; y < x; y++)
{
// Walk through the path until a flag is encountered.
// Flag 1 = the next '\'.
// Flag 2 = (y > (z + 8)).

// Remove any space characters from the path name.
if ((buff [y] == ' ' ) && (y <= (z + 8)))
{
int a = y;

while (buff [y])
{
buff [y] = buff [y + 1];
y++;
}

y = a;
}

// Do nothing, go to the next character.
else if ((buff [y] != '\\') && (y <= (z + 8)));

// Reset the section counter 'z' to the last '\' counted
// if this occurs before the 8 character limit is exceeded..
else if ((buff [y] == '\\') && (y <= (z + 9)))
z = y;

else
{
// Assign the ~ char to the next charcter.
y = y - 2;
buff [y] = '~';

// Assign the 1 char to the next charcter.
y++;
buff [y] = '1';

y++;
int w = y;

// This code processes the path correctly if the
// the last part of the path does not contain a
// file name that has more than 12 characters
// including the ext.
//************************
while (buff [y] != '\\')
{
// move the characters down 1 step.
while (w < x)
{
buff [w] = buff [w + 1];
w++;
}

// This code handles the last directory
// conversion. otherwise the previos code
// never finds the next '\'.
if (y == x)
break;

// As we modify the path the path gets shorter.
x--;

// Reset the counter for the next run.
w = y;
}
//************************

z = y;
}
}
}
 
Hehe , there is such a WinAPI called GetShortPathName or the VCL equivalent ExtractShortPathName to convert a long path name into short 8.3 form.

hennep, about the MinimizeName function. Can you tell us which size label, what font(name,size,style) ,what string you wanted to display and the maxlength. I just want to test if I get the same results.


 
Hello BTecho, I noticed in CBuilder5 ExtractShortPathName does NOT work correctly in some circumstances. I forget which exactly, but I believe it was circumstances with spaces and/or ()s in the file name.
 
Butthead,

I don't need 8.3 filenames, I just need to shorten a long path.
But I keep this code for future reference. ( In case in run into the problem Chris mentioned ).

thanks
 
wasnt meant to solve your problem.
only as reference example. the fellow above
stated a case were the vcl function didn't
function properly. Another reason to write your
own functions to handle these simple problems.
The code above handles the spaces perfectly.

you can use the code above to accomplish your task.
the modifications are relatively easy..
 
Hi fellows.

butthead, thanks for helping :)

hennep,

I seem to get the same results as you, clipping of the last letter occurs.

I also need a function that calculates the occupied space taking into account the font, fontsize etc. The only one I have found so far is DrawText.

Looking at the filectrl.pas file, it has the source for MinimizeName, you can see they use TextWidth

Snip from BCB Help

Description

Use TextWidth to determine the length a string will occupy in the image. TextWidth indicates whether a given string will fit in the available space. Other graphical elements in the image such as lines, or additional strings can be positioned to accommodate the width of the text.

TextWidth returns the same value as TextExtent(Text).cx.

Anyways, after all the talk, seems nothing is 100% perfect :-(

#include <vcl.h>
#include <FileCtrl.hpp>
#include <Shlwapi.h>
#pragma hdrstop

#include &quot;Unit2.h&quot;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource &quot;*.dfm&quot;
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void TForm2::Shorten_File_Name (char *string, int x)
// x = the target path length. If the extracted file name
// is large enough it will possibly exceed the target length.
// Windows filenames can get quite large and you may want to
// allow the ability to shorten that if exceeds a certain length.
// The function will handle this but the results as coded may
// not fit your preferences.

// input - C:\Program Files\Borland\CBuilder5\Examples\Apps\Cursors\readme.txt
// output - C:\Progr...\readme.txt

{
int length = strlen (string);
int a;
int b;

if (length > x)
{
char *buff1 = new char [60]; // filename max length
char *buff2 = new char [256];

strcpy (buff1, ExtractFileName(string).c_str ());

a = x - strlen (buff1);

if (a > 3) // if there is enough room.
{
for (b = 0; b < (a - 2); b++)
buff2 = string ;

buff2 = NULL;
}
else // this just appends the file name to the drive name
// with the &quot;...&quot; in the middle.
{
for (b = 0; b < 3; b++)
buff2 = string ;

buff2 = NULL;
}

strcat (buff2, &quot;...\\&quot;);
strcat (buff2, buff1);

strcpy (string, buff2);
delete buff1;
delete buff2;
}

Label2->Caption=string;
}
//---------------------------------------------------------------------------


void __fastcall TForm2::FormCreate(TObject *Sender)
{
Label1->AutoSize = false;
Label1->Caption = &quot;123456789012345&quot;;
Label1->Color = clWhite;
Label1->Width = 105;
Label1->Font->Name = &quot;MS Sans Serif&quot;;
Label1->Font->Color = clWindowText;
Label1->Font->Size = 8;
Label1->Font->Style = TFontStyles() << fsBold;

Label2->AutoSize = false;
Label2->Caption = &quot;123456789012345&quot;;
Label2->Color = clWhite;
Label2->Width = 105;
Label2->Font->Name = &quot;MS Sans Serif&quot;;
Label2->Font->Color = clWindowText;
Label2->Font->Size = 8;
Label2->Font->Style = TFontStyles() << fsBold;

Label3->AutoSize = false;
Label3->Caption = &quot;123456789012345&quot;;
Label3->Color = clWhite;
Label3->Width = 105;
Label3->Font->Name = &quot;MS Sans Serif&quot;;
Label3->Font->Color = clWindowText;
Label3->Font->Size = 8;
Label3->Font->Style = TFontStyles() << fsBold;

Label4->AutoSize = false;
Label4->Caption = &quot;123456789012345&quot;;
Label4->Color = clWhite;
Label4->Width = 105;
Label4->Font->Name = &quot;MS Sans Serif&quot;;
Label4->Font->Color = clWindowText;
Label4->Font->Size = 8;
Label4->Font->Style = TFontStyles() << fsBold;

Label5->AutoSize = false;
Label5->Caption = &quot;123456789012345&quot;;
Label5->Color = clWhite;
Label5->Width = 105;
Label5->Font->Name = &quot;MS Sans Serif&quot;;
Label5->Font->Color = clWindowText;
Label5->Font->Size = 8;
Label5->Font->Style = TFontStyles() << fsBold;

//-------Label1
Label1->Caption = MinimizeName(&quot;c:\\windows\\command.com&quot;, Label1->Canvas, Label1->Width );

//-------Label2
Shorten_File_Name (&quot;c:\\windows\\command.com&quot;, 15);

//-------Label3
RECT BoundingRect = { 0, 0, Label3->Width, Label3->Height };
String strText;
strText = &quot;c:\\windows\\command.com&quot;;
DrawText( Label3->Canvas->Handle, strText.c_str(), strText.Length(), &BoundingRect, DT_MODIFYSTRING | DT_PATH_ELLIPSIS );
Label3->Caption = strText;

//-------Label4
Label4->Caption = &quot;c:\\windows\\command.com&quot;;
char *p = Label4->Caption.c_str();
HANDLE TempDC = CreateCompatibleDC( this->GetDeviceContext(this->Handle) );
DrawText( TempDC, p, strlen(p), &BoundingRect, DT_PATH_ELLIPSIS + DT_MODIFYSTRING );
Label4->Caption = p;
DeleteDC( TempDC );

//-------Label5
char buffer_1[MAX_PATH] = &quot;c:\\windows\\command.com&quot;;
char *lpStr;

lpStr = buffer_1;
int retval = PathCompactPath(Label5->Canvas->Handle,lpStr,Label5->Width );

Label5->Caption = lpStr;
//-------

}
//---------------------------------------------------------------------------




There are some new API functions PathCompactPath and PathCompactPathEx , you must have a minimum of IE4 installed though. See MSDN for more info( and there is AbbreviateName from the MS MFC file filelist.cpp.

When I have more time I'll try to look into this in more detail.
 
Glad I could help.
Seeing how you implemented the code has
given me some ideas to tweek the function.
Give me a week or so and I will have
version 8.0 up or was it 7.0.
I cant remember. Got to many projects
going at once.

tomcruz.net
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top