 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
johnp Guest
|
Posted: Fri May 04, 2007 1:51 am Post subject: The Joys of Text |
|
|
I have a StringGrid and can write text in its cells when DefaultDrawing =
true.
With DefaultDrawing = false I'm trying to writing text with API DrawText()
- but no text appears in the cells.
The (simplified) code is
String thing = "Hello" ;
int lenny = thing.Length() ;
LPRECT square = static_cast<LPRECT>(&(Form5->StringGrid1->CellRect(0,1))) ;
LPCTSTR stringy = static_cast<LPCTSTR>(thing.c_str()) ;
DrawText(Form5->StringGrid1->Canvas->Handle, stringy, lenny, square,
DT_LEFT |DT_VCENTER |DT_SINGLELINE);
In debug everything looks ok, & DrawText() returns 15 (the font height)
Why doesn't the text appear ?
johnp |
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Fri May 04, 2007 5:08 am Post subject: Re: The Joys of Text |
|
|
"johnp" <john.pearson (AT) No_Spam (DOT) co.uk> wrote in message
news:463a4b4b (AT) newsgroups (DOT) borland.com...
| Quote: | LPRECT square =
static_cast<LPRECT>(&(Form5->StringGrid1->CellRect(0,1))) ; |
You can't do it that way. CellRect() returns a temporary TRect that
will go out of scope immediately, leaving you with a dangling pointer
to invalid memory. Store the result into a local TRect instance
instead, and then use its memory address when needed, ie:
TRect square = Form5->StringGrid1->CellRect(0,1);
| Quote: | LPCTSTR stringy = static_cast<LPCTSTR>(thing.c_str()) ;
|
That would not be a valid conversion if you were compiling for
Unicode, as LPCTSTR would be a wchar_t* instead of a char* pointer.
| Quote: | Why doesn't the text appear ?
|
I notice that you are retreiving the TRect for a specific cell. How
many cells do you actually have? You need to have a separate TRect
for each cell being drawn.
Where exactly are you calling this code from? It needs to be in the
OnDrawCell event handler, if it is not already. That event gives you
the TRect for the cell currently being drawn, so you don't need to
call CellRect() manually. For example:
void __fastcall TForm5::StringGrid1DrawCell(TObject* Sender, int
ACol, int ARow, TRect Rect, TGridDrawState State)
{
String thing = "Hello" ;
StringGrid1->Canvas->FillRect(Rect);
DrawText(StringGrid1->Canvas->Handle, thing.c_str(),
thing.Length(), &Rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
Gambit |
|
| Back to top |
|
 |
johnp Guest
|
Posted: Mon May 07, 2007 5:39 pm Post subject: Re: The Joys of Text |
|
|
"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote in message
news:463a795a$1 (AT) newsgroups (DOT) borland.com...
| Quote: |
"johnp" <john.pearson (AT) No_Spam (DOT) co.uk> wrote in message
news:463a4b4b (AT) newsgroups (DOT) borland.com...
LPRECT square =
static_cast<LPRECT>(&(Form5->StringGrid1->CellRect(0,1))) ;
You can't do it that way. CellRect() returns a temporary TRect that
will go out of scope immediately, leaving you with a dangling pointer
to invalid memory. Store the result into a local TRect instance
instead, and then use its memory address when needed, ie:
TRect square = Form5->StringGrid1->CellRect(0,1);
I did notice that Form5->StringGrid1->CellRect(0,1) kept giving
different values in debug. OK - the code should be
TRect gridnum = Form5->StringGrid1->CellRect(0,1) ;
LPRECT square = static_cast<LPRECT>(&gridnum) ;
LPCTSTR stringy = static_cast<LPCTSTR>(thing.c_str()) ;
That would not be a valid conversion if you were compiling for
Unicode, as LPCTSTR would be a wchar_t* instead of a char* pointer.
OK Unicode not a problem (yet) as the strings are vanilla ascii
Why doesn't the text appear ?
I notice that you are retreiving the TRect for a specific cell. How
many cells do you actually have? You need to have a separate TRect
for each cell being drawn.
the number of cells will be determined at run time (depends on the
number of user defined DLLs found in a subdir).
Where exactly are you calling this code from?
a loop which puts a string from each DLL in each StringGrid cell
It needs to be in the OnDrawCell event handler, if it is not already.
That
event gives you the TRect for the cell currently being drawn, so you don't
need to call CellRect() manually. For example:
void __fastcall TForm5::StringGrid1DrawCell(TObject* Sender, int
ACol, int ARow, TRect Rect, TGridDrawState State)
{
String thing = "Hello" ;
StringGrid1->Canvas->FillRect(Rect);
DrawText(StringGrid1->Canvas->Handle, thing.c_str(),
thing.Length(), &Rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
Gambit
I hear you Remy but I'm stuck.
I have 3 choices - Call OnDrawCell by event, by another function, or
directly.
By event:-
BCB6 Help states OnDrawCell "Occurs when a cell in the grid needs to be
drawn" (
Can anyone be more specific ?
By another function
Chandler in "more on stringgrids" states InvalidateCell() will fire the
handler
but InvalidateCell is not inherited by TStringGrid
How do I call InvalidateCell ?
Call OnDrawCell directly ,
but it contains a strange argument, a TGridDrawState type.
BCB6 Help & Chandler describe a TGridDrawState as a set
Grepping in \include reveals it's a synonym for
Set<Grids_3, gdSelected, gdFixed> and the Set class seems to be
template<class T, unsigned char minEl, unsigned char maxEl
class RTL_DELPHIRETURN Set : SetBase<T, minEl, maxEl
Set __fastcall operator +(const Set& rhs) const //Union
Set __fastcall operator -(const Set& rhs) const //Difference
Set __fastcall operator *(const Set& rhs) const //Intersection
I give up - can anyone describe TGridDrawState ?
Johnp |
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Mon May 07, 2007 10:10 pm Post subject: Re: The Joys of Text |
|
|
"johnp" <john.pearson (AT) No_Spam (DOT) co.uk> wrote in message
news:463f1e17 (AT) newsgroups (DOT) borland.com...
| Quote: | I did notice that Form5->StringGrid1->CellRect(0,1) kept giving
different values in debug. OK - the code should be
TRect gridnum = Form5->StringGrid1->CellRect(0,1) ;
LPRECT square = static_cast<LPRECT>(&gridnum) ;
|
You are still hard-coding the values to CellRect(), so all of your
drawing is going to go to the same cell each time, even when you want
it to go somewhere else.
| Quote: | the number of cells will be determined at run time (depends on
the number of user defined DLLs found in a subdir).
snip
a loop which puts a string from each DLL in each StringGrid cell
|
What exactly are you trying to custom-draw in the TStringGrid to begin
with? Your drawing code is not using the grid's Cells[][] property at
all, which would be the ideal place to store your string values for
each cell. TStringGrid already draws the Cells for you, so what about
the native drawing are you trying to change?
| Quote: | I have 3 choices - Call OnDrawCell by event, by another function,
or directly.
|
TStringGrid itself will call the OnDrawCell event handler directly
whenever it needs to. You do not call it yourself directly at all.
| Quote: | BCB6 Help states OnDrawCell "Occurs when a cell in the grid
needs to be drawn" (
Can anyone be more specific ?
|
What is unclear about it? The OS knows when the grid needs to refresh
its display onscreen, so it will send WM_ERASEBKGND and WM_PAINT
messages to the grid telling it to redraw itself onto an HDC that the
OS provides. That will in turn trigger the OnDrawCell event so that
the programmer can decide what each individual cell will look like.
| Quote: | Chandler in "more on stringgrids" states InvalidateCell() will fire
the handler but InvalidateCell is not inherited by TStringGrid
|
InvalidateCell() tells the grid, and thus the OS, that the grid needs
to refresh its display at a later time at the OS's descretion. It
will then issue the drawing messages again as described above.
Invalidating a control is the programmer's way of telling the OS that
an update is needed as son as possible, but the actual drawing still
needs to be done separately.
| Quote: | Call OnDrawCell directly ,
|
Do not do that.
| Quote: | but it contains a strange argument, a TGridDrawState type.
BCB6 Help & Chandler describe a TGridDrawState as a set
|
That is not a problem. When the TStringGrid triggers the OnDrawCell
event, it fills in that argument automatically for you. You can then
query the Set to know which flags are enabled, so that you know what
characteristics to apply to each cell being drawn.
| Quote: | I give up - can anyone describe TGridDrawState ?
|
Did you read the documentation for Set? For TGridDrawState? They are
both described.
Gambit |
|
| Back to top |
|
 |
johnp Guest
|
Posted: Tue May 08, 2007 6:03 pm Post subject: Re: The Joys of Text |
|
|
"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote in message
news:463f5d70$1 (AT) newsgroups (DOT) borland.com...
| Quote: |
"johnp" <john.pearson (AT) No_Spam (DOT) co.uk> wrote in message
news:463f1e17 (AT) newsgroups (DOT) borland.com...
snip
What exactly are you trying to custom-draw in the TStringGrid to begin
with? <snip
|
I am trying to
a. Render the text in the cells under user control
b. control the highlighted cell, irrespective of which cell is bugged.
c. change the highlighted cell when an external event takes place,
d. add a check box to each cell.
At your urging I'm modified the code to that below
I think it's working properly - it puts the text in the cells correctly . .
.. .
//--------------------------------------------------------------
//Writes the filter description to the Form5 StringGrid
int displaydlls(int no_dlls)
{
HINSTANCE dllhandle ;
int i = 0 ;
do
{
dllhandle = LoadLibrary( (*(passivedllpaths + i)).c_str() ) ;
if(dllhandle==0) . . error msg
else pflabel = (text)GetProcAddress(dllhandle, "_flabel") ;
if (pflabel==0) . . . . error msg
else Form5->StringGrid1->Cells[0][i] = pflabel();
}
i++ ;
Form5->StringGrid1->RowCount = no_dlls ;
}
while(i<no_dlls) ;
Form5->StringGrid1->RowCount = no_dlls ; //save no of rows
return 0 ;
}//-------------------------------------------------
//Fills the Cells
void __fastcall TForm5::drawacell(TObject *Sender, int ACol, int ARow, TRect
&Rect, TGridDrawState State)
{
int no_dlls = Form5->StringGrid1->RowCount ;
HDC chandle = Form5->StringGrid1->Canvas->Handle ;
for(int i=0;i<no_dlls;i++)
{
String Slabel = Form5->StringGrid1->Cells[0][i] ;
LPCTSTR label = static_cast<LPCTSTR>(Slabel.c_str()) ;
int len = Slabel.Length() ;
LPRECT square = static_cast<LPRECT>(&(Form5->StringGrid1->CellRect(0,i))) ;
DrawText(chandle, label, len, square, DT_LEFT |DT_VCENTER |DT_SINGLELINE) ;
}
return ;
}
//---------------------------------------------------
Form here on I'll try to follow D. Chandler's "More on StringGrids" to
implement b, c and d
Gambit - Thanks for all your help
| Quote: | Did you read the documentation for Set? For TGridDrawState? They are
both described.
Gambit
I went back to BCB6 "Help" again and found the description of the Set Class |
template
As someone else on these forums said "It's in there - you just have to find
it"
JohnP |
|
| Back to top |
|
 |
johnp Guest
|
Posted: Tue May 08, 2007 11:13 pm Post subject: Re: The Joys of Text |
|
|
Sorry - typo in first function.
It should be
//-----------------------------------------------
//Writes the filter description to the Form5 StringGrid
int displaydlls(int no_dlls)
{
HINSTANCE dllhandle ;
int i = 0 ;
do
{
dllhandle = LoadLibrary( (*(passivedllpaths + i)).c_str() ) ;
if(dllhandle==0) . . error msg
else pflabel = (text)GetProcAddress(dllhandle, "_flabel") ;
if (pflabel==0) . . . . error msg
else Form5->StringGrid1->Cells[0][i] = pflabel();
i++ ;
}
while(i<no_dlls) ;
Form5->StringGrid1->RowCount = no_dlls ; //save no of rows
return 0 ;
//----------------------------------------------
"johnp" <john.pearson (AT) No_Spam (DOT) co.uk> wrote in message
news:46407509 (AT) newsgroups (DOT) borland.com...
| Quote: | "Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote in message
news:463f5d70$1 (AT) newsgroups (DOT) borland.com...
"johnp" <john.pearson (AT) No_Spam (DOT) co.uk> wrote in message
news:463f1e17 (AT) newsgroups (DOT) borland.com...
snip
What exactly are you trying to custom-draw in the TStringGrid to begin
with? <snip
I am trying to
a. Render the text in the cells under user control
b. control the highlighted cell, irrespective of which cell is bugged.
c. change the highlighted cell when an external event takes place,
d. add a check box to each cell.
At your urging I'm modified the code to that below
I think it's working properly - it puts the text in the cells correctly .
. . .
//--------------------------------------------------------------
//Writes the filter description to the Form5 StringGrid
int displaydlls(int no_dlls)
{
HINSTANCE dllhandle ;
int i = 0 ;
do
{
dllhandle = LoadLibrary( (*(passivedllpaths + i)).c_str() ) ;
if(dllhandle==0) . . error msg
else pflabel = (text)GetProcAddress(dllhandle, "_flabel") ;
if (pflabel==0) . . . . error msg
else Form5->StringGrid1->Cells[0][i] = pflabel();
}
i++ ;
Form5->StringGrid1->RowCount = no_dlls ;
}
while(i<no_dlls) ;
Form5->StringGrid1->RowCount = no_dlls ; //save no of rows
return 0 ;
}//-------------------------------------------------
//Fills the Cells
void __fastcall TForm5::drawacell(TObject *Sender, int ACol, int ARow,
TRect &Rect, TGridDrawState State)
{
int no_dlls = Form5->StringGrid1->RowCount ;
HDC chandle = Form5->StringGrid1->Canvas->Handle ;
for(int i=0;i<no_dlls;i++)
{
String Slabel = Form5->StringGrid1->Cells[0][i] ;
LPCTSTR label = static_cast<LPCTSTR>(Slabel.c_str()) ;
int len = Slabel.Length() ;
LPRECT square = static_cast<LPRECT>(&(Form5->StringGrid1->CellRect(0,i)))
;
DrawText(chandle, label, len, square, DT_LEFT |DT_VCENTER |DT_SINGLELINE)
;
}
return ;
}
//---------------------------------------------------
Form here on I'll try to follow D. Chandler's "More on StringGrids" to
implement b, c and d
Gambit - Thanks for all your help
Did you read the documentation for Set? For TGridDrawState? They are
both described.
Gambit
I went back to BCB6 "Help" again and found the description of the Set
Class template
As someone else on these forums said "It's in there - you just have to
find it"
JohnP
|
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Tue May 08, 2007 11:41 pm Post subject: Re: The Joys of Text |
|
|
"johnp" <john.pearson (AT) No_Spam (DOT) co.uk> wrote:
| Quote: | I am trying to
snip |
You will have to set up a separate struct/class to hold all of that information on a per-cell basis. You can use the TStringGrid's Objects property to hold the info. Or you can set up your own list/array separately. Your OnDrawCell event handler can then access that information when needed to know how to draw each individual cell. You can then update that information whenever you want and then Invalidate the grid to update the drawing.
| Quote: | At your urging I'm modified the code to that below
I think it's working properly - it puts the text
in the cells correctly . .
|
You need to get rid of the loop inside your OnDrawCell event handler. The event is already triggered on a per-cell basis. It tells you exactly which cell to draw. Draw that cell and no other cell each time the event is triggered.
You also did not fix the other problems I told you about earlier.
Your code should look more like the following:
struct CellInfo
{
bool Highlighted;
bool Checked;
};
int displaydlls(int no_dlls)
{
HINSTANCE dllhandle;
if( no_dlls <= 0 )
Form5->StringGrid1->RowCount = 1; // can't be empty
else
Form5->StringGrid1->RowCount = no_dlls;
for(int i = 0; i < no_dlls; ++i)
{
dllhandle = LoadLibrary( (*(passivedllpaths + i)).c_str() ) ;
if( !dllhandle )
{
// error msg...
continue;
}
pflabel = (text) GetProcAddress(dllhandle, "_flabel");
if( !pflabel )
{
// error msg...
continue;
}
Form5->StringGrid1->Cells[0][i] = pflabel();
Form5->StringGrid1->Objects[0][i] = new CellInfo;
}
return 0;
}
void __fastcall TForm5::StringGrid1DrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State)
{
String Slabel = StringGrid1->Cells[ACol][ARow];
CellInfo *Info = (CellInfo) StringGrid1->Objects[ACol][ARow];
TRect r = Rect;
if( (Info) && (Info->Highlighted) )
{
StringGrid1->Canvas->Brush->Color = clHighlight;
StringGrid1->Canvas->Font->Color = clHighlightText;
}
else
{
StringGrid1->Canvas->Brush->Color = StringGrid1->Color;
StringGrid1->Canvas->Font->Color = StringGrid1->Font->Color;
}
StringGrid1->Canvas->FillRect(r);
if( Info )
{
UINT State = DFCS_BUTTONCHECK | DFCS_ADJUSTRECT;
if( Info->Checked )
State |= DFCS_CHECKED;
::DrawFrameControl(StringGrid1->Canvas->Handle, &r, DFC_BUTTON, State);
}
::DrawText(StringGrid1->Canvas->Handle, Slabel.c_str(), Slabel.Length(), &r, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
void __fastcall TForm5::StringGrid1MouseDown(TObject* Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
int Col, Row;
StringGrid1->MouseToCell(X, Y, Col, Row);
if( (Col == 0) & (Row >= 0) )
{
RECT r;
// calculate RECT of checkbox...
if( ::PtInRect(&r, Point(X, Y) )
{
CellInfo *Info = (CellInfo*) StringGrid1->Objects[Col][Row];
if( Info )
{
Info->Checked = !Info->Checked;
StringGrid1->Invalidate();
}
}
}
}
void __fastcall TForm5::HighlightCell(int Row, bool Highlighted)
{
CellInfo *Info = (CellInfo*) StringGrid1->Objects[0][Row];
if( Info )
{
Info->Checked = Highlighted;
StringGrid1->Invalidate();
}
}
Gambit |
|
| Back to top |
|
 |
johnp Guest
|
Posted: Tue May 15, 2007 6:46 pm Post subject: Re: The Joys of Text |
|
|
Remy
Thanx for the tutorial.
I got the check boxes working fine- they look good !
Final code below
Johnp
//----------------------------------
struct cellinfo
{
bool highlighted ;
bool checked ;
cellinfo(bool, bool ) ;
} ;
//for later; At boot show which cells have user created data
cellinfo::cellinfo(bool lite = false , bool chckd = false)
{
highlighted = lite ;
checked = chckd ;
}
//----------------------------------
//Writes the filter description to the Form5 StringGrid
int displaydlls(int no_dlls, TObject *Sender)
{
HINSTANCE dllhandle ;
for(int i=0;i<no_dlls;i++)
{
dllhandle = LoadLibrary( (*(passivedllpaths + i)).c_str());
if(dllhandle==0) . . . error
else pflabel = (text)GetProcAddress(dllhandle, "_flabel");
if (pflabel==0) . . . error
else Form5->StringGrid1->Cells[0][i] = pflabel();
//above calls OnDrawCell AFTER exiting for(.) loop
//Form5->StringGrid1->Objects[0][i] = new cellinfo ;
//E2034 can't convert cellinfo to TObject
cellinfo* cellptr = new cellinfo(false, false) ;
Form5->StringGrid1->Objects[0][i] = reinterpret_cast<TObject*>(cellptr);
}
if(no_dlls<=0) Form5->StringGrid1->RowCount = 1 ;
else Form5->StringGrid1->RowCount = no_dlls ;
return 0 ;
}
//------------------------------------------------------
//OnDrawCell handler. - The background calls this handler repeatedly
//AFTER all the text bearing cells have been assigned.
void __fastcall TForm5::drawacell(TObject *Sender, int ACol, int ARow, TRect
&Rect, TGridDrawState State)
{
int no_dlls = Form5->StringGrid1->RowCount ;
HDC chandle = Form5->StringGrid1->Canvas->Handle ;
String Slabel = Form5->StringGrid1->Cells[0][ARow] ;
// cell for highlighting is assigned by caller via Objects ptr
cellinfo *info =
reinterpret_cast<cellinfo*>(Form5->StringGrid1->Objects[0][ARow]) ;
if ((info) && (info->highlighted))
{
StringGrid1->Canvas->Brush->Color = clHighlight ; // Background colour of
selected text
StringGrid1->Canvas->Font->Color = clHighlightText ; // Colour of selected
text
}
else
{
StringGrid1->Canvas->Brush->Color = StringGrid1->Color ; //Background colour
of control
StringGrid1->Canvas->Font->Color = StringGrid1->Font->Color ;
}
TRect ORect = Rect ;
Form5->StringGrid1->Canvas->FillRect(ORect) ; //int FillRect(HDC, CONST
RECT*, HBRUSH)
if (info)
{
ORect.right = ORect.left + StringGrid1->DefaultRowHeight ; //To position
checkbox on left side of row
ORect.bottom = ORect.top + StringGrid1->DefaultRowHeight ;
UINT State = DFCS_BUTTONCHECK | DFCS_ADJUSTRECT ; //DrawFrameControl flags
if(info->checked) State = State | DFCS_CHECKED ; //defined in winuser.h
::DrawFrameControl(StringGrid1->Canvas->Handle, &ORect, DFC_BUTTON, State) ;
}
ORect = Rect ;
ORect.left = ORect.left + StringGrid1->DefaultRowHeight ;
ORect.bottom = ORect.top + StringGrid1->DefaultRowHeight ;
::DrawText(StringGrid1->Canvas->Handle, Slabel.c_str(), Slabel.Length(),
&ORect,
DT_LEFT | DT_VCENTER | DT_SINGLELINE ) ; //Draws text in middle of rect
}
//------------------------------------------------
//StringGrid OnMouseDown Handler
void __fastcall TForm5::showfilter(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{ //X, Y are coords of mouse pointer in client area of Sender
interrogate_dlls(Button, X, Y ) ;
int no_dlls = Form5->StringGrid1->RowCount ;
int Col, Row ;
StringGrid1->MouseToCell(X, Y, Col, Row) ;
//create Rect for check_box & position it to left of text
if((Col==0) & (Row>=0) & (no_dlls>0)) //?(Row>=0)
{
RECT r ; //StringGrid1->DefaultRowHeight
r.left = 1 ;
r.top = 1 ;
r.right = StringGrid1->DefaultRowHeight ;
r.bottom = no_dlls * StringGrid1->DefaultRowHeight ;
if ( ::PtInRect(&r, Point(X, Y))) //Is Point inside r
{
cellinfo *info =
reinterpret_cast<cellinfo*>(Form5->StringGrid1->Objects[0][Row]) ;
if(info)
{
info->checked = !info->checked ;
StringGrid1->Invalidate() ;
}
}
}
} |
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Tue May 15, 2007 11:48 pm Post subject: Re: The Joys of Text |
|
|
"johnp" <john.pearson (AT) No_Spam (DOT) co.uk> wrote in message
news:4649b9c8 (AT) newsgroups (DOT) borland.com...
| Quote: | //above calls OnDrawCell AFTER exiting for(.) loop
|
That is perfectly fine and normal.
| Quote: | if(no_dlls<=0) Form5->StringGrid1->RowCount = 1 ;
else Form5->StringGrid1->RowCount = no_dlls ;
|
You need to set the RowCount property before you can fill in the
Cells, not afterwards. Otherwise, the Cells won't physically exist to
hold your data.
| Quote: | int no_dlls = Form5->StringGrid1->RowCount ;
|
Get rid of that. It is of no use inside the OnDrawCell event handler.
| Quote: | HDC chandle = Form5->StringGrid1->Canvas->Handle ;
|
You are not using that for anything, so remove that as well.
| Quote: | ORect.right = ORect.left + StringGrid1->DefaultRowHeight ;
//To position checkbox on left side of row
|
Use the RowHeights property instead of the DefaultRowHeight property.
Even better, use the Height() of the TRect itself.
| Quote: | ORect.bottom = ORect.top + StringGrid1->DefaultRowHeight ;
|
You should not be doing that at all when calculating the Text area.
Use the full TRect height that is given to you.
| Quote: | RECT r ; //StringGrid1->DefaultRowHeight
r.left = 1 ;
r.top = 1 ;
r.right = StringGrid1->DefaultRowHeight ;
r.bottom = no_dlls * StringGrid1->DefaultRowHeight ;
|
You should be using the CellRect() method instead. MouseToCell()
tells you the exact cell that is being clicked on, so you can grab the
TRect for just that cell and then adjust it accordingly for the
checkbox area.
Here is the code that works for me:
struct CellInfo
{
bool Highlighted;
bool Checked;
CellInfo() : Highlighted(false), Checked(false) {}
};
void AdjustRectForCheckBox(TRect &R)
{
R.Left += 2;
R.Top += 2;
R.Bottom -= 2;
R.Right = (R.Left + R.Height());
}
int displaydlls(int no_dlls)
{
HINSTANCE dllhandle;
if( no_dlls <= 0 )
Form1->StringGrid1->RowCount = 1; // can't be empty
else
Form1->StringGrid1->RowCount = no_dlls;
for(int i = 0; i < no_dlls; ++i)
{
dllhandle = LoadLibrary( (*(passivedllpaths +
i)).c_str() ) ;
if( !dllhandle )
{
// error msg...
continue;
}
pflabel = (text) GetProcAddress(dllhandle, "_flabel");
if( !pflabel )
{
// error msg...
continue;
}
Form1->StringGrid1->Cells[0][i] = pflabel();
Form1->StringGrid1->Objects[0][i] = (TObject*) new
CellInfo;
// Note: make sure that you manually free the CellInfo
items
// before freeing the form, or else the memory will be
leaked!
}
return 0;
}
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int
ACol, int ARow, TRect &Rect, TGridDrawState State)
{
String Slabel = StringGrid1->Cells[ACol][ARow];
CellInfo *Info = (CellInfo*) StringGrid1->Objects[ACol][ARow];
TRect r = Rect;
if( (Info) && (Info->Highlighted) )
{
StringGrid1->Canvas->Brush->Color = clHighlight;
StringGrid1->Canvas->Font->Color = clHighlightText;
}
else
{
StringGrid1->Canvas->Brush->Color = StringGrid1->Color;
StringGrid1->Canvas->Font->Color =
StringGrid1->Font->Color;
}
StringGrid1->Canvas->FillRect(r);
if( Info )
{
AdjustRectForCheckBox(r);
UINT State = DFCS_BUTTONCHECK | DFCS_ADJUSTRECT;
if( Info->Checked )
State |= DFCS_CHECKED;
::DrawFrameControl(StringGrid1->Canvas->Handle, &r,
DFC_BUTTON, State);
r = Rect;
r.Left += (r.Height() + 2);
}
::DrawText(StringGrid1->Canvas->Handle, Slabel.c_str(),
Slabel.Length(), &r, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
void __fastcall TForm1::StringGrid1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
int Col, Row;
StringGrid1->MouseToCell(X, Y, Col, Row);
if( (Col == 0) & (Row >= 0) )
{
CellInfo *Info = (CellInfo*)
StringGrid1->Objects[Col][Row];
if( Info )
{
TRect r = StringGrid1->CellRect(Col, Row);
AdjustRectForCheckBox(r);
if( ::PtInRect(&r, Point(X, Y)) )
{
Info->Checked = !Info->Checked;
StringGrid1->Invalidate();
}
}
}
}
Gambit |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|