Odd drawing issue (black cells) in TStringGrid - delphi

I encountered something really really really odd with TStringGrid (Delphi XE). I have seen that sometimes when I click the first line in my grid, it turns black (or shows scrambled canvas 'stolen' from other controls on form).
It happens ONLY in certain configurations, when the grid receives focus. Once you click another area in the grid everything looks ok until the focus is moved to another TStringGrid.
How to reproduce:
put TWO string grids on a form
set them as shown below (Update: I realized that goRowSelect and goEditing must be 'true')
click the first cell in one grid -> nothing happens
click the first cell in the second grid -> the first cell gets black (see screenshot)
The problem appears also in other circumstances (not necessary to have 2 grids on a form), but I managed to reproduce it only when I have 2 grids.
object grid1: TStringGrid <------- same for Grid2
Left = 2
Top = 8
Width = 422
Height = 381
BevelEdges = [beLeft, beTop]
DefaultColWidth = 80
DefaultRowHeight = 15
DoubleBuffered = True
FixedCols = 0
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goDrawFocusSelected, goColSizing, goEditing, goRowSelect, goFixedHotTrack]
ParentDoubleBuffered = False
TabOrder = 1
end
Any idea on how to fix this?

I can reproduce your problem with XE3 as well. After I have reset ParentDoubleBuffered to True, the problem is gone.
Generally speaking, when I see odd black rectangle in a control, I will first check the ParentDoubleBuffered settings. I saw you have enabled double buffering for the two grids. Do you have any special reason to do that? If you intend to avoid flickering during resizing or cell update, there are some techniques helpful.

Related

Firemonkey - Combobox highlight item at mouse position

Nearly every application will highlight a comboboxes' item at the current mouse position.
In Firemonkey Embarcadero changed this behavior.
Image1:
In this case ListBoxItem3 should be highlighted - but it isn't.
I then selected ListBoxItem2 and opened the combobox again.
Image2:
ListBoxItem2 keeps being selected even tho ListboxItem4 should be.
As you can see I was using TListBox Items in this example.
In the StyleBook I added a new StyleObject (a blue rectangle) with a TFloatAnimation so i could add a "fake" selection.
But it sadly didn't work.
Image3:
So here i am after spending quite some time trying to figure out how to select a comboboxes' item on mouse over movements.
Someone know a way to achieve this?
This is a new behaviour introduced by new versions (from X3 onwards), you can set DropDownKind = ddkCustom (default value ddkNative) for emulate old behavior.
Note that using Custom as DropDownKind you obtain a behaviour that it's slightly different from the previous one, since it sets the itemIndex property value immediately, but it shouldn't be a big problem ...

Why scrolling a TListView calls for an entire form repaint - Delphi Firemonkey

Starting with a blank mobile app, I added a TlistView, a TCircle, and a TMemo. None of the controls had any alignment other than the default and they are all direct children of the main form.
In the OnPaint event of the ListView, I put this:
Memo1.Lines.Add('ListView paint'),
For the circle OnPaint:
Memo1.Lines.Add('Circle paint');
When I ran the app the results were that scrolling the listview resulted in lots of "Listview paint" and "Circle paint" getting added to the memo, both items always getting added at the same time. Why does scrolling a listview (or scrolling the memo) call an entire form repaint?
There's a line in the call stack that makes me think the entire form is getting repainted:
Fmx.Platform.Ios.TFMXView3D.drawRect(0x14659ec0,{origin = {x = 0, y = 0}, size = {width = 768, height = 1024}})
I'm want to know if this is supposed to be happening or not. This is causing poor performance in a listivew I have because a chart is constantly getting repainted.
Judging by the comments this appears to be a issue with Firemonkey, however it has been specified as by design. From the QC issue
GPU Canvas in FireMonkey that is used on mobile platforms always repaints the entire form, which is by design.
As a workaround, there is TRasterEffect, which can be dropped on the form and parented to one of the controls. If done so, the control will be rendered to internal image first and then such image will be drawn, alleviating the problem.

What settings or scenarios break animations' triggers from firing?

I am trying to animate a checkbox through stylebook by;
Making a layout and naming it 'ch_style1'
Adding another layout naming it 'layout' ( Align = Left )
Adding a TRectangle ( Align = Left; HitTest = False )
Setting fill color to animate through TColorAnimation
The TColorAnimation ( Enabled = True; Inverse = True; Trigger = IsMouseOver=true; InverseTrigger = IsMouseOver=false )
Adding a TText and a TShadowEffect
The problem only shows up in my main application where there are a lot of controls though hidden. Each view can contain up to 30-40 controls. There are no performance issues at all. The style designer IDE even shows the animations on the control but running the application suggests as if the IsMouseOver trigger doesn't fire. I have faced success, only if I do it for controls on a new form.
As its all in the IDE, I can't give any code to help my case, the dfm even sits above 600KB... So please enlighten me with your experiences and any possible areas I may look for the solution. Thank you.
There's an inherent bug in FireMonkey (both the original from XE2 and FM2 from XE3) where the animations fail mid-way. It's not you, it's FireMonkey!

How do you rename a Status Bar Panel in Delphi 2010

I have just added a new panel to StatusBar1 and it is called 5 - TStatusPanel. I want to give it a different name but I can't remember how to do this.
I want to rename 5 - TStatusPanel to 5 - GripArea. As you can see from the image I have done this before (see Num, Caps, AM/PM) but I can't remember how I did this. It sucks to get old.
Just change the Text property of the TStatusPanel. This is what is displayed in the status panel editor. Of course, this will make the text visible in the panel! Normally, in code, you access the status panels using the StatusBar1.Panels[PanelIndex] array. PanelIndex is the zero-based index of the panel. I always declare constants such as
STATUS_FILE_POSITION = 0;
STATUS_FILE_SAVED = 1;
STATUS_LONG_TEXT = 2;
STATUS_ZOOM_CONTROL = 3;
and use these to remember the panels. (The code above is from my text editor.)
So I can do, for instance,
StatusBar.Panels[STATUS_FILE_SAVED].Text := 'Modified';
Here's a tip that would have saved some hunting: right-click on the form, View As Text. Now you'll see the form layed out as properties, and you could have found the control, seen how the other panels were named, and fix the last one.
Alt+F12 to toggle the text view on/off.

Creating a ComboBox with one or more separator items?

I'm using Delphi7 and I'd like to have a ComboBox with separator items (Just like in popup menus).
I've seen this beautifully implemented in Mozilla Sunbird (I know, it's not Delphi...) the following way:
The separator item is a simple gray line
drawn in the center of the item
If you hover over the separator with
the mouse, the selection doesn't
appear
If the user clicks the separator,
it's not selected either AND the
combobox doesn't closeup.
No. 1 could be implemented using DrawItem. I could live without No. 2 because I have no idea about that.
For No. 3 I'm asking for your help. I've figured out that straight after closing up a CBN_CLOSEUP message is sent to the combobox.
I thought about hooking the window proc and if CBN_CLOSEUP is sent to a certain combobox then countering it. But I'm unsure if this is the best solution, or maybe there are other, more elegant ways?
Whatever the solution is, I'd like to have a standard ComboBox which supports WinXP/Vista/7 theming properly.
Thanks!
Edit: For a working component please see this thread:
Can you help translating this very small C++ component to Delphi?
I played around with making unclickable separator items (as described in this answer) and ran into several UI glitches. The problem is that combo boxes have several aspects to their behavior that can be hard to get exactly right:
Pressing the up and down arrow keys navigates the list while the list is dropped down.
Pressing Enter closes the dropped down list, selecting the current item.
Pressing Escape closes the dropped down list, selecting the current item (if the current item was chosen with the up and down arrow keys) or the last selected item.
If the combo box has the focus, then pressing the up and down arrow keys to changes the current selection without displaying the list.
If the combo box has the focus, then typing anything selects the combo box item matching whatever is typing.
If the combo box has the focus, then pressing F4 drops down the combo box list, which can then be controlled by keyboard or mouse.
Ensuring that disabled separator items don't respond to any of these events (plus any other events which I may be missing, e.g., screen readers?) seems fraught with error.
Instead, the approach I'm using is to draw the separator as part of the item:
Use a variable height owner draw combo box.
Add 3 pixels to the height for any items that need separators.
Draw a horizontal line at the top of each item needing a separator.
Here's some C++Builder code to accomplish this; translating it to Delphi should be easy enough.
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control,
int Index, TRect &Rect, TOwnerDrawState State)
{
bool draw_separator = NeedsSeparator(Index) &&
!State.Contains(odComboBoxEdit);
TCanvas *canvas = dynamic_cast<TCustomCombo*>(Control)->Canvas;
canvas->FillRect(Rect);
TRect text_rect = Rect;
// Add space for separator if needed.
if (draw_separator) {
text_rect.Top += 3;
}
canvas->TextOut(text_rect.Left + 3,
(text_rect.Top + text_rect.Bottom) / 2 -
canvas->TextHeight(ComboBox1->Items->Strings[Index]) / 2),
ComboBox1->Items->Strings[Index]);
// Draw a separator line above the item if needed.
if (draw_separator) {
canvas->Pen->Color = canvas->Font->Color;
canvas->MoveTo(Rect.Left, Rect.Top + 1);
canvas->LineTo(Rect.Right, Rect.Top + 1);
}
}
void __fastcall TForm1::ComboBox1MeasureItem(
TWinControl * /* Control */, int Index, int &Height)
{
Height = ComboBox1->ItemHeight;
// Add space for the separator if needed.
if (Index != -1 && NeedsSeparator(Index)) {
Height += 3;
}
}
What you want is an owner-drawn combobox. See this: http://delphi.about.com/od/vclusing/a/drawincombobox.htm
Also, this seems to solve making the item unclicable:
http://borland.newsgroups.archived.at/public.delphi.vcl.components.using.win32/200708/0708225320.html
As far as I know there is no VCL way of doing that, so you'll have to subclass the combobox. It would be nice to create component encapsulating those functionalities so you can reuse them easily.
God bless
If you want your controls to look good use the free SpTBXLib. It supports combo style components which popup a popup menu with lines.

Resources