Board index » cppbuilder » ListView->Font->Charset not working properly?

ListView->Font->Charset not working properly?

Hi all,

I have a form with, among others, a ListView. The form also has a
StatusBar. The form's font is set to be Arial with the East Europe
charset. When I put a Label or a Memo on the form, they show correct
text, using the assigned charset. But, no matter what I do, I can't make
the ListView or the StatusBar display text properly. It looks like they
are always using the ANSI charset, with no regards to the actual charset
setting. I'm using BCB4 Standard and Windows 95, with patch #1 applied.
Does anybody know what's happening and how to fix this problem or get
around it?

TIA
--
Wlodek (a.k.a. Tony) Szafran

 

Re:ListView->Font->Charset not working properly?


Wlodek,
Set the list box's and status bar's ParentFont property to 'True'.  This is
the default for the status bar, but not the list box.  Verified with BCB 3.

Dave

Re:ListView->Font->Charset not working properly?


Quote
Dave Curry wrote:

> Wlodek,
> Set the list box's and status bar's ParentFont property to 'True'.  This is
> the default for the status bar, but not the list box.  Verified with BCB 3.

> Dave

List boxes are working properly regarding the charset. I was asking
about the ListView. With the ListView and StatusBar, it doesn't matter
whether the ParentFont is set to "true" or not.

Again, ListView and StatusBar don't seem to care about the charset
setting.
--
Wlodek (a.k.a. Tony) Szafran

Re:ListView->Font->Charset not working properly?


Quote
>List boxes are working properly regarding the charset. I was asking
>about the ListView. With the ListView and StatusBar, it doesn't matter
>whether the ParentFont is set to "true" or not.

Sorry for the misunderstanding.  BTW, I tried using TListView, and
everything seems fine to me as long as ParentFonts is set to 'true'.
However, I think I am not looking for what you are, namely characters that
would only be found in the East European char set.  I have no idea what
characters those might be, nor how I would enter them on my US keyboard -
some hints in that area might help me.

Unfortunately, if you have ParentFont set true, and things still aren't
working, it may just be yet another bug.

Good luck,
Dave

Re:ListView->Font->Charset not working properly?


Quote
Dave Curry wrote:

> Sorry for the misunderstanding.  BTW, I tried using TListView, and
> everything seems fine to me as long as ParentFonts is set to 'true'.
> However, I think I am not looking for what you are, namely characters that
> would only be found in the East European char set.  I have no idea what
> characters those might be, nor how I would enter them on my US keyboard -
> some hints in that area might help me.

If you're willing to give it a try, please enter some text in ListView's
column header or item caption, it doesn't matter. The characters from
the East European set cannot be entered directly from the US keyboard,
but the combination of Alt + numeric keypad digits will do the trick.
Please try the following characters: Alt-0165, Alt-0198, Alt-0202,
Alt-0185, Alt-0230, Alt-0234. If everything is working properly you
should see letters "ACEace" with cute little tails in the ListView when
youre done typing. If you only see strange characters from the upper
ANSI set, then this is the problem I'm describing. For comparison, you
could enter the same text into a label's caption and see that it's
working properly there, provided that you're using a combination of a
proper font (Arial will do fine) and EASTEUROPE_CHARSET.

Thanks a lot for your time and your help.
--
Wlodek (a.k.a. Tony) Szafran

Re:ListView->Font->Charset not working properly?


Hi Wlodek,

Quote
> If you're willing to give it a try, please enter some text in ListView's
> column header or item caption.  If everything is working properly you
> should see letters "ACEace" with cute little tails in the ListView when
> youre done typing.

What version of comctl32 do you have?  Using Arial / EASTEUROPE_CHARSET and your
prescribed key sequences, I see "ACEace" with the curly tails on them in
TListView.  However, this was tested on a system with comctl32 v. 4.71 (IE4).
If it comes down to it, you can use Custom Draw to render each ListItem in a
separately created font.  I can provide an example if needed.

Good luck.

--------------------------------------
Damon Chandler

http://bcbcaq.freeservers.com
Answers to <Commonly Asked Questions>
52064929

Re:ListView->Font->Charset not working properly?


Quote
Damon Chandler wrote:

> Hi Wlodek,
> > If you're willing to give it a try, please enter some text in ListView's
> > column header or item caption.  If everything is working properly you
> > should see letters "ACEace" with cute little tails in the ListView when
> > youre done typing.

> What version of comctl32 do you have?  Using Arial / EASTEUROPE_CHARSET and your
> prescribed key sequences, I see "ACEace" with the curly tails on them in
> TListView.  However, this was tested on a system with comctl32 v. 4.71 (IE4).

Thank you for checking this. In the meantime I found that indeed the
comctl32.dll is the culprit. When I was doing my tests, I had the
comctl32 version 5.8 installed by MS IE5. I reinstalled version 4.72,
taken from the MS web site and everything in my program looked as it
should. Of course, with that version of the dll, MS IE5 is not working -
and I need it for other stuff. So, I reinstalled the newest version, and
predictably, my program shows broken characters now.

I'm wondering now if the new comctl32.dll is broken regarding the font
charset in some controls, or doesn't BCB's VCL know how to talk to that
dll.

Anyway, this situation is giving me headaches, because I don't want the
users of my program lining up to tell me that on their computer the
letters aren't displayed properly.

Quote
> If it comes down to it, you can use Custom Draw to render each ListItem in a
> separately created font.  I can provide an example if needed.

If it's not too much bother, please do that, along with column headers,
if you can. Thanks for responding, I appreciate it.

Quote
> Good luck.

> --------------------------------------
> Damon Chandler

> http://bcbcaq.freeservers.com
> Answers to <Commonly Asked Questions>
> 52064929

Regards.
--
Wlodek (a.k.a. Tony) Szafran

Re:ListView->Font->Charset not working properly?


Hi Wlodek,

Quote
> Thank you for checking this. In the meantime I found that indeed the
> comctl32.dll is the culprit.
> Anyway, this situation is giving me headaches, because I don't want the
> users of my program lining up to tell me that on their computer the
> letters aren't displayed properly.

I know how you feel... the whole situation of IE5 / version limited functions
are certainly trifling.

Quote
> If it's not too much bother, please do that, along with column headers,
> if you can. Thanks for responding, I appreciate it.

Before looking at the example (below), try to read the following articles to get
a primer on Custom Draw in general, and specific to TListView and the ListView's
header...

http://bcbcaq.freeservers.com/CustomDraw_TV.html
http://bcbcaq.freeservers.com/CustomDraw_LV.html
http://bcbcaq.freeservers.com/CustomDraw_LVHeader.html

Here's the example...

// in header...
    Controls::TWndMethod OldListViewWP;
    void __fastcall NewListViewWP(TMessage &Msg);

    // map the WM_NOTIFY message in the Parent of the
    // "custom drawn control"
    void __fastcall WMNotify(TMessage &Msg);

BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_NOTIFY, TMessage, WMNotify)
END_MESSAGE_MAP(TForm)

// in source...
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    OldListViewWP = ListView1->WindowProc;
    ListView1->WindowProc = NewListViewWP;

Quote
}

void __fastcall TForm1::NewListViewWP(TMessage &Msg)
{
    if (Msg.Msg == WM_NOTIFY)
    {
        // see if the notification is from the Custom Draw
        // service and from the header control
        LPNMCUSTOMDRAW lpnmcd = (NMCUSTOMDRAW *)Msg.LParam;
        if (lpnmcd->hdr.code == NM_CUSTOMDRAW &&
            lpnmcd->hdr.hwndFrom == GetDlgItem(ListView1->Handle, 0))
            {
                // test the drawing stage
                switch(lpnmcd->dwDrawStage)
            {
                // prior to painting...
                case CDDS_PREPAINT:
                {
                    // tell Windows we want individual
                    // notification of each item being drawn
                    Msg.Result = CDRF_NOTIFYITEMDRAW;
                    return;
                }
                // upon painting...
                case CDDS_ITEMPREPAINT:
                {
                    int Idc = SaveDC(lpnmcd->hdc);

                    // extract the relevant info from the
                    // NMCUSTOMDRAW structure
                    TRect Rect = lpnmcd->rc;
                    int Index = lpnmcd->dwItemSpec;
                    unsigned int State = lpnmcd->uItemState;
                    AnsiString text =
                    ListView1->Columns->Items[Index]->Caption;

                    // Create a new TCanvas, assign it to the
                    // provided device context, then set the
                    // Canvas's font to your charset
                    TCanvas *HeaderCanvas = new TCanvas();
                    HeaderCanvas->Handle = lpnmcd->hdc;
                    HeaderCanvas->Font->Name = "Arial";
                    HeaderCanvas->Font->Size = ListView1->Font->Size;
                    HeaderCanvas->Font->Charset = EASTEUROPE_CHARSET;
                    HeaderCanvas->Brush->Color = clBtnFace;

                    // if depressed
                    if (State & CDIS_SELECTED)
                    {
                        Frame3D(HeaderCanvas, Rect, clBtnShadow,
                                clBtnHighlight, 2);
                        HeaderCanvas->FillRect(Rect);
                        HeaderCanvas->TextRect(Rect, Rect.Left + 4,
                                               Rect.Top + 1, text);
                    }
                    // if normal
                    else
                    {
                        Frame3D(HeaderCanvas, Rect, clBtnHighlight,
                                clBtnShadow, 2);
                        HeaderCanvas->FillRect(Rect);
                        HeaderCanvas->TextRect(Rect, Rect.Left + 3,
                                               Rect.Top, text);
                    }

                    // restore the device context
                    RestoreDC(lpnmcd->hdc, Idc);
                    HeaderCanvas->Handle = 0;
                    delete HeaderCanvas;

                    // tell Windows we drew the header
                    Msg.Result = CDRF_SKIPDEFAULT;
                    return;
                }
                default:
                {
                    // let Windows handle this stage
                    Msg.Result = CDRF_DODEFAULT;
                    return;
                }
            }
        }
    }

    // un-subclass the ListView
    if (Msg.Msg == WM_DESTROY) ListView1->WindowProc = OldListViewWP;
        OldListViewWP(Msg);

Quote
}

void __fastcall TForm1::WMNotify(TMessage &Msg)
{
    LPNM_LISTVIEW lpnm = (NM_LISTVIEW *)Msg.LParam;

    // see if the message is a Custom Draw message
    if (lpnm->hdr.code == NM_CUSTOMDRAW)
    {
        // see if the message is from the ListView
        if (lpnm->hdr.hwndFrom == ListView1->Handle)
        {
            LPNMLVCUSTOMDRAW lplvcd = (NMLVCUSTOMDRAW *)Msg.LParam;
            switch (lplvcd->nmcd.dwDrawStage)
            {
                // prior to painting the items...
                case CDDS_PREPAINT:
                {
                    Msg.Result = CDRF_NOTIFYITEMDRAW;
                    return;
                }
                case CDDS_ITEMPREPAINT:
                {
                    // tell Windows we want notification of
                    // each subitem being drawn
                    Msg.Result = CDRF_NOTIFYSUBITEMDRAW;
                    return;
                }
                case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
                {
                    int Idc = SaveDC(lplvcd->nmcd.hdc);

                    // Create a new TCanvas, assign it to the
                    // provided device context, then set the
                    // Canvas's font to your charset
                    TCanvas *LVCanvas = new TCanvas();
                    LVCanvas->Handle = lplvcd->nmcd.hdc;
                    LVCanvas->Font->Name = "Arial";
                    LVCanvas->Font->Size = ListView1->Font->Size;
                    LVCanvas->Font->Charset = EASTEUROPE_CHARSET;

                    // get other important info
                    int ItemIndex = lplvcd->nmcd.dwItemSpec;
                    int ColumnIndex = lplvcd->iSubItem;
                    TListItem *Item = ListView1->Items->Item[ItemIndex];

                    // get the item caption to draw, and
                    // get the bounding rectangle of the
                    // caption and corresponding icon
                    RECT CaptionRect, IconRect;
                    AnsiString text;
                    if (ColumnIndex == 0)
                    {
                        // caption
                        text = Item->Caption;

                        // caption and icon rectangles
                        CaptionRect.left = LVIR_LABEL;
                        IconRect.left = LVIR_ICON;
                        SNDMSG(ListView1->Handle, LVM_GETITEMRECT,
                               ItemIndex, (LPARAM)&CaptionRect);
                        SNDMSG(ListView1->Handle, LVM_GETITEMRECT,
                               ItemIndex, (LPARAM)&IconRect);
                    }
                    else if (ColumnIndex <= Item->SubItems->Count)
                    {
                        // caption
                        text = Item->SubItems->Strings[ColumnIndex - 1];

                        // caption rectangle
                        CaptionRect.left = LVIR_LABEL;
                        CaptionRect.top = ColumnIndex;
                        SNDMSG(ListView1->Handle, LVM_GETSUBITEMRECT,
                               ItemIndex, (LPARAM)&CaptionRect);
                    }

                    // grab a pointer to the ListView's ImageList
                    TImageList *ImageList = ListView1->SmallImages;

                    // assign selected visual attributes
                    if ((lplvcd->nmcd.uItemState & CDIS_SELECTED)
                        && ColumnIndex == 0)
                    {
                        // have the ImageList draw in selected mode
                        ImageList->DrawingStyle = dsSelected;
                        ImageList->BlendColor = clHighlight;

                        // set the text andd background colors
                        // to indicate selected
                        LVCanvas->Font->Color = clHighlightText;
                        LVCanvas->Brush->Color = clHighlight;
                    }
                    else
                    {
                        // have the ImageList draw normally
                        ImageList->DrawingStyle = dsNormal;

                        // set the text andd background colors
                        // to indicate normal
                        LVCanvas->Font->Color = ListView1->Font->Color;
                        LVCanvas->Brush->Color = ListView1->Color;
                    }

                        // draw the caption
                    DrawText(LVCanvas->Handle, text.c_str(),
                             text.Length(), &CaptionRect,
                             DT_LEFT | DT_VCENTER |
                             DT_SINGLELINE | DT_END_ELLIPSIS);

                    // draw the icon
                    if (ColumnIndex == 0)
                        ImageList->Draw(LVCanvas, IconRect.left,
                                        IconRect.top, Item->ImageIndex);

                    // restore the device context
                    RestoreDC(lplvcd->nmcd.hdc, Idc);
                    LVCanvas->Handle = 0;
                    delete LVCanvas;

                    // tell Windows we drew the item
                    Msg.Result = CDRF_SKIPDEFAULT;
                    return;
                }

                // otherwise have Windows draw the item
                default: Msg.Result = CDRF_DODEFAULT;
                return;
...

read more »

Re:ListView->Font->Charset not working properly?


Quote
Damon Chandler wrote:

> [cut]

> Before looking at the example (below), try to read the following articles to get
> a primer on Custom Draw in general, and specific to TListView and the ListView's
> header...

> http://bcbcaq.freeservers.com/CustomDraw_TV.html
> http://bcbcaq.freeservers.com/CustomDraw_LV.html
> http://bcbcaq.freeservers.com/CustomDraw_LVHeader.html

> Here's the example...

> [cut]

Thank you very much, this is great stuff - the example and your
articles. Now I'm working on custom-drawing the list view headers, using
the code provided by you, and at last I can see the text displayed
properly. For list view items and sub-items, I'm going to employ BCB4's
built-in custom-drawing events, using your code, of course.

Again, thanks a lot.

Regards.
--
Wlodek (a.k.a. Tony) Szafran

Other Threads