• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 549
  • Last Modified:

No focus / highlight on FontName ComboBox wanted

Hi Expert,

I would like a Combobox showing fontnames for a RichEdit, that fills itself with all present font names, *not* to be highlighted and focussed.

The line that causes this, is marked with ///

constructor TMemo.Create(AOwner : TComponent);
begin
   inherited;
   m_NoDataChange := false;
   GetFontNames;
end;

procedure TMemo.GetFontNames;
var
  DC: HDC;
begin
  DC := GetDC(0);
  EnumFonts(DC, nil, @EnumFontsProc, Pointer(FontName.Items)); ///
  ReleaseDC(0, DC);
  FontName.Sorted := True;
end;

Does any of you know how to 'unfocus' / 'unhighlight' the control?

Thanks,
Ron dW
0
Ron_de_Weijze
Asked:
Ron_de_Weijze
  • 8
  • 6
1 Solution
 
geobulCommented:
Hi,

If by 'highlighted' you mean no item to be selected then add the following lines at the end of GetFontNames procedure:

  FontName.ItemIndex := -1;
  FontName.Text := '';

For the combobox not to be focused - set the focus to another control (inside your TMemo) by:
  self.Memo.SetFocus; // for instance

I presume your TMemo component consists of several components like Panel (TPanel), Memo (TRichEdit) and FontName (TComboBox) on the Panel.

Regards, Geo
0
 
Ron_de_WeijzeAuthor Commented:
Hi Geo,

The situation is as you assumed.
However, your first option doesn't work in this case.
Maybe because this is reserved / assembled / precompiled code?

I will try your second option. That should work. Will let you know.

Thanks,
Ron dW
0
 
Ron_de_WeijzeAuthor Commented:
Hello Geo,

In my app clicking a treenode creates the Memo, dynamically. The focus should be on the treenode: when it changes, the Memo changes as well. Yet, there is a 'second focus' if I may call it like that, in the combobox that filled itself with font names, as described above. Changing the focus from the combobox to another control, does not seem to be possible. At best, I get the focus from the treenode to move to one of the controls around the memo, but this is not supposed to happen. All the time, the combobox stays highlighted or focussed or or just colored blue (actually, not the box itself but the background of the font name text).

Ron dW
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Ron_de_WeijzeAuthor Commented:
Points increased.
0
 
geobulCommented:
Hi Ron,

1. If you just comment the line EnumFonts(...) what happens? Try another thing also and see the result:

procedure TMemo.GetFontNames;
var
  DC: HDC;
begin
  DC := GetDC(0);
  // EnumFonts(DC, nil, @EnumFontsProc, Pointer(FontName.Items)); ///
  FontName.Items.Add('Font1');
  FontName.Items.Add('Font2');
  ReleaseDC(0, DC);
  FontName.Sorted := True;
end;

2. Would you post some more code? I'm interested in the following:
- who, when and how creates FontName combobox?
- what does EnumFontsProc do?
- what does your treenode click event do?

Regards, Geo
0
 
Ron_de_WeijzeAuthor Commented:
Geo, good questions ;)

1. Without that line, the box is not highlighted. However, there are neither fontnames in the drop-down menu. With the lines you added, fontnames Font1 and Font2 are there.

2.
Q: who creates FontName combobox?
A:
constructor TNotePrp.Create(AOwner : TComponent);
begin
   inherited;
   m_NoDataChange := false;
   GetFontNames; ///
end;

Q: what does EnumFontsProc do?
A: EnumFontsProc Retrieves information about available fonts.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fontext_4cyr.asp

Q: what does the treenode click event do?
A:
   begin
      UpdateProperties(TV_Container.Selected);
      UpdateTVToolBar(TV_Container.Selected);
      UpdatePopUpMenu(TV_Container.Selected);
   end;

These are all Cmtrls functions. TV_Container: TTreeView.



0
 
geobulCommented:
Thank you. The picture doesn't become more clear to me though.

1. GetFontNames doesn't create a combobox (in the form you posted it in the beginning). It just fills it in. FontName is a field/property of TNotePrp or one of its ancestors I suppose. So, FontName creation is still a mistery ;-)

2. EnumFontsProc is a function you should have already written. Please post the code of that function. I've used EnumFontFamilies instead (adapted to receive TStrings parameter in lpData):

function EnumFontFamProc(var lp: TEnumLogFont;
 var tm: TNewTextMetric;
 dwType: DWORD;
 lpData: lParam): Integer; stdcall;
begin
 Result := 1;
 with TStrings(lpData) do
 begin
   Add(lp.elfLogFont.lfFaceName);
 end;
end;

and the call should be:
  EnumFontFamilies(DC,nil,@EnumFontFamProc,Integer(FontName.Items));

I don't think there will be any difference but you may try that.

3. You said 'clicking a treenode creates the Memo, dynamically'. I can't see that :-(

Regards, Geo
0
 
Ron_de_WeijzeAuthor Commented:
1. FontName is the name of the ComboBox on form NotePrp. Creating the form is creating the box, plus a RichEdit (the memo).

2. function EnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric;
  FontType: Integer; Data: Pointer): Integer; stdcall;
begin
  TStrings(Data).Add(LogFont.lfFaceName);
  Result := 1;
end;

Tried EnumFontFamProc but the effect is the same.

3. NotePrp is constructed at runtime, including the memo (richedit). Sorry if that is not what is called dynamic.


0
 
geobulCommented:
Thanks. I should have understand all that already :-)

OK. The next question is how are you using/showing the NotePrp form. I've created a similar form and set FontName.Text to nothing in design-time:
---------
type
  TNotePrp = class(TForm)
    FontName: TComboBox;
    Memo1: TMemo;
  private
    { Private declarations }
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    procedure GetFontNames;
  end;

var
  NotePrp: TNotePrp;

implementation

{$R *.DFM}

function EnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric;
  FontType: Integer; Data: Pointer): Integer; stdcall;
begin
  TStrings(Data).Add(LogFont.lfFaceName);
  Result := 1;
end;

constructor TNotePrp.Create(AOwner : TComponent);
begin
  inherited;
  GetFontNames;
end;

procedure TNotePrp.GetFontNames;
var
  DC: HDC;
begin
  DC := GetDC(0);
  try
    EnumFonts(DC, nil, @EnumFontsProc, Pointer(FontName.Items));
  finally
    ReleaseDC(0, DC);
  end;
  FontName.Sorted := True;
end;

end.
-------
and showed it in two ways over a panel on another form:
-----
procedure TForm1.Button1Click(Sender: TObject);
begin
  if NotePrp = nil then begin
    NotePrp := TNotePrp.Create(Application);
// First way:
//    with NotePrp do begin
//      Parent := Panel1;
//      Left := 0;
//      Top := 0;
//      Show;
//    end;
// Second way:
    with NotePrp do begin
      Panel1.DockSite := true;
      ManualDock(Panel1);
      Show;
    end;
  end;
end;
-----
I cannot reproduce the problem here. There is no text at all in the combobox, nothing is highlighted or focused. FontName contains all the font names.

Are you getting that form from a DLL?

Regards, Geo
0
 
Ron_de_WeijzeAuthor Commented:
Hi Geo,

Indeed your code doesn't reproduce the problem.

Here are some selections from my (running) program.
What is marked with /// seems more relevant to me.
Not all lines are shown.

{Startup}

procedure TNavForm.FormCreate(Sender: TObject);  ///
var
   TabSheet : TTabSheet;
   Prop : TPropertyFrm;

begin

   // Fill the PageControl with the property forms
   // Container Properties
   TabSheet := TTabSheet.Create(Self);
   Prop := TContainerPrp.Create(TabSheet);
   Prop.Parent := TabSheet;
   Prop.Align := alClient;
   TabSheet.PageControl := PC_Property; ///
   PC_Property.Pages[cContainerPage].TabVisible := FALSE; ///
   Prop.Visible := TRUE;

   // NotePool Properties
   TabSheet := TTabSheet.Create(Self);
   Prop := TNotePoolPrp.Create(TabSheet);
   Prop.Parent := TabSheet;
   Prop.Align := alClient;
   TabSheet.PageControl := PC_Property; ///
   PC_Property.Pages[cNotePoolPage].TabVisible := FALSE; ///
   Prop.Visible := TRUE;

   // NoteItem Properties
   TabSheet := TTabSheet.Create(Self);
   Prop := TNotePrp.Create(TabSheet);   ///
   Prop.Parent := TabSheet;
   Prop.Align := alClient;
   TabSheet.PageControl := PC_Property; ///
   PC_Property.Pages[cNoteItemPage].TabVisible := FALSE;
   Prop.Visible := TRUE; ///

end;

constructor TNotePrp.Create(AOwner : TComponent);
begin
   inherited; /// at startup
   m_NoDataChange := false;
   GetFontNames; ///
end;

function TCustomTreeView.GetSelected: TTreeNode;  /// notes get collected
begin
  if HandleAllocated then
  begin
    if FRightClickSelect and Assigned(FRClickNode) then
      Result := FRClickNode
    else
      Result := Items.GetNode(TreeView_GetSelection(Handle));
  end
  else Result := nil;
end;

procedure TNavForm.Refresh(ChangedItem : TObject; SheetsAlso : Boolean);
   begin
      UpdateProperties(TV_Container.Selected); ///
      UpdateTVToolBar(TV_Container.Selected);
      UpdatePopUpMenu(TV_Container.Selected);
   end;
end;

procedure TNavForm.UpdateProperties(SelectedItem : TTreeNode);
begin
   if TObject(SelectedItem.Data) is TContainer then
   begin
      TContainerPrp(PC_Property.Pages[cContainerPage].Controls[0]).ShowContents(SelectedItem.Data);
      PC_Property.ActivePage := PC_Property.Pages[cContainerPage];
   end
end;

{Mainform is shown now.}

procedure TNavForm.TV_ContainerKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
   Refresh(nil, FALSE);
end;


0
 
geobulCommented:
Hi,

Sorry for the delay.

I tried using TabSheet as parent as it was in your code above and found only one problem in the creation/filling mechanism: TabSheet needs a parent before creating PropForm on it:

type
  TForm1 = class(TForm)
    Button1: TButton;
    PC_Property: TPageControl;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses unit2; // TNotePrp

procedure TForm1.Button1Click(Sender: TObject);
var
  TabSheet : TTabSheet;
  Prop : TNotePrp;
begin
  TabSheet := TTabSheet.Create(self);
  TabSheet.Parent := PC_Property; // <-- this line
  if NotePrp = nil then begin
    NotePrp := TNotePrp.Create(TabSheet);
    with NotePrp do begin
      Parent := TabSheet;
      Align := alClient;
      Visible := true;
    end;
    TabSheet.PageControl := PC_Property;
    TabSheet.TabVisible := true;
  end;
end;

Again there was no selection or whatsoever on the form.

What left unchecked is TNavForm.UpdateProperties procedure and especially the following line which I cannot test here:

TContainerPrp(PC_Property.Pages[cContainerPage].Controls[0]).ShowContents(SelectedItem.Data);

i.e. the way you're displaying/showing that page and the form on it. And most probably you're updating the values of some controls there.

Regards, Geo
0
 
Ron_de_WeijzeAuthor Commented:
Thanks, Geo.

I will give you the points even though the problem is still there. I need to understand the mechanisms involved better before we can work on this again. Besides it is not so urgent, merely a matter of cosmetics.

So I will get back to this one later and add a link to the follow-up.

Thanks again,

Ron dW
0
 
Ron_de_WeijzeAuthor Commented:
Forgot to mention that of course I tested your latest suggestions..
0
 
geobulCommented:
Many thanks for the points. I'll do my best in the next question. Good luck :-)
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 8
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now