This is turning into a real showstopper, as most of the frames in my app
(which has around 100 frames) have no TGraphic controls showing as a result
(I'm at a loss to explain why some do and some don't!) . I'm sure my
customers will not put up with having to guess what a particular edit
control is for!
I'm using runtime packages so I can't patch the VCL source and no,
recompiling the packages isn't going to help either, because I would have to
change the names (borland prohibits distributing a recompiled vcl70.bpl)
which would then break all the third party controls...
I've tried setting parent background to false, tried turning on
doublebuffered but then check boxes just paint as a black backgound....
Borland, please fix this now, not in just D8 but in a D7 update!
--
Regards
Vincent Parrett
Atozed Software http://www.atozedsoftware.com
---------------
Automate your Build Process with FinalBuilder
I've made the workaround listed for QC3850 visible. It seems to work for a
simple test app, eg:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TFrame2 = class(TFrame)
Panel1: TPanel;
Label1: TLabel;
private
{ Private declarations }
protected
procedure PaintWindow(DC: HDC); override;
public
{ Public declarations }
end;
implementation
{$R *.dfm}
{ TFrame2 }
procedure TFrame2.PaintWindow(DC: HDC);
begin
if DC = 0 then
inherited;
end;
end.
Although of course with this method you'd need to add code like this for
each frame. Please let me know whether this helps.
--
Dave Nottage (TeamB)
The problem I have with this is that I don't write all the frames, the
program has a plugin api and the frames are registered as part of a plugin.
I already have around a hundred frames that would need to be updated...
What does the TGraphicControl in question do? Display an image?
Do you have a proprietary control that descends from TGraphicControl?
Change the base control to TCustomControl if possible.
TGraphicControls are potentially dangerous according to my experience, I
try to avoid them because they don't have their own device context.
A simpler solution might to put it on a Windowed control with the same
size, at least the device context will have the same position as the
TGraphicControl then.
--
Ingvar Nilsen
Erm... TLabel is a TGraphic control descendant... so avoiding them would
take a hell of a lot a work! It's happening with any TGraphicControl
Descendant.
Ok, I can see why you called it a showstopper.
I thought maybe it only happened to some proprietary controls.
You are in trouble...
But if it is reproducible, it should be possible to fix it, Dave's
suggestion could be simplified by having all frames descend from one
that implements his suggestion. Or?
Waiting for an update is evidently not the way to go.
BTW, this kind of challenge is something I would love to take, if I only
had the time.. :-\
--
Ingvar Nilsen
Damn right, and I've already wasted days on trying to work around this.
> But if it is reproducible, it should be possible to fix it, Dave's
> suggestion could be simplified by having all frames descend from one
> that implements his suggestion. Or?
That will have to be the last resort, because the frames are all plugins and
users can create their own plugins... and there are a whole other bunch of
issues with distributing dcp's etc and dfms and I don't want to go there..
> Waiting for an update is evidently not the way to go.
Unfortunately for me it's looking like its either that or move back to D6
(another few days worth of work at least!).
> BTW, this kind of challenge is something I would love to take, if I only
> had the time.. :-\
I'd rather borland just do it... I've already got a ton of code in my app to
work around other D7 bugs (all to do with the added theme support) but some
bugs I just cannot work around.
<snip>
Another way:
unit FrameFix;
interface
uses
Forms, Windows;
type
TFrame = class(Forms.TFrame)
protected
procedure PaintWindow(DC: HDC); override;
end;
implementation
{ TFrame }
procedure TFrame.PaintWindow(DC: HDC);
begin
if DC = 0 then
inherited;
end;
end.
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, FrameFix;
type
TFrame2 = class(TFrame)
Panel1: TPanel;
Label1: TLabel;
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.dfm}
end.
ie, just add the FrameFix unit to the uses clause, making sure it appears
after Forms in the clause.
You still need to update all the units that have frames in them, however
this method simplifies the fix.
--
Dave Nottage (TeamB)
> Unfortunately for me it's looking like its either that or move back
> to D6 (another few days worth of work at least!).
Moving back to D6 would imply that the people who write their own plugins
will have to at least recompile. Instead of recompiling for D6, they might
be able to use the simpler fix that I've just posted in another reply in
this thread.
> I'd rather borland just do it..
So would I <g>
--
Dave Nottage (TeamB)
I'm working on FinalBuilder 2, hasn't been released yet, but when it is
people will have to recompile their plugins after upgrading anyway.
> > I'd rather borland just do it..
>
> So would I <g>
I'm not holding my breath.
So hook the wndprocs. A very generic solution, works with any form whether
you know the type at compile time or not.
-Danny
That's what I'm working on at the moment... with limited success at the
moment... will post here if I have any success.
Ok, well I've had some success hooking the wndprocs, although I now have an
annoying flicker problem.. I created a component to hook the wndproc at
runtime when the frames are instanciated (using some potential workarounds
posted in QC) :
unit FBD7ThemeHack;
interface
uses
classes,forms,messages;
type
TFrameWinProcHook = class(TComponent)
private
FFrame : TFrame;
FOldWinProc : TWndMethod;
protected
procedure FrameWinProc(var Message: TMessage);
procedure SetFrame(const Value: TFrame);
procedure Notification(AComponent: TComponent; Operation: TOperation);
override;
public
constructor Create(AOwner : TComponent);override;
destructor Destroy;override;
property Frame : TFrame read FFrame write SetFrame;
end;
implementation
uses
Themes,Types,windows,controls;
type
TFrameCrack = class(TFrame);
{ TFrameWinProcHook }
constructor TFrameWinProcHook.Create(AOwner: TComponent);
begin
inherited;
end;
destructor TFrameWinProcHook.Destroy;
begin
if FFrame <> nil then
begin
FFrame.WindowProc := FOldWinProc;
FFrame := nil;
end;
inherited;
end;
procedure TFrameWinProcHook.FrameWinProc(var Message: TMessage);
var
inv,newInv : boolean;
InvRect,Dummy : TRect;
begin
case Message.Msg of
WM_PRINTCLIENT :
begin
with TWMPrintClient(Message) do
if (Result <> 1) then
if ((Flags and PRF_CHECKVISIBLE) = 0) or FFrame.Visible then
begin
Inv := GetUpdateRect(FFrame.Handle,InvRect,False);
TFrameCrack(FFrame).PaintHandler(TWMPaint(Message));
NewInv := GetUpdateRect(FFrame.Handle,Dummy,false);
if Inv <> NewInv then
InvalidateRect(FFrame.Handle,@InvRect,False);
message.Result := 1;
end
else
FOldWinProc(message)
else
FOldWinProc(message);
end;
WM_ERASEBKGND :
begin
if not FFrame.DoubleBuffered or (Message.wParam = Message.lParam) then
begin
if ThemeServices.ThemesEnabled and Assigned(FFrame.Parent) and
(csParentBackground in FFrame.ControlStyle) then
begin
{ Get the parent to draw its background into the control's
background.}
ThemeServices.DrawParentBackground(FFrame.Handle,
TWMEraseBkgnd(Message).DC, nil, False);
end
else
begin
FillRect(TWMEraseBkgnd(Message).DC, FFrame.ClientRect,
FFrame.Brush.Handle);
end;
end;
Message.Result := 1;
end;
else
FOldWinProc(Message);
end;
end;
procedure TFrameWinProcHook.Notification(AComponent: TComponent; Operation:
TOperation);
begin
inherited;
if (AComponent = FFrame) and (Operation = opRemove) then
begin
FFrame.WindowProc := FOldWinProc;
FFrame := nil;
end;
end;
procedure TFrameWinProcHook.SetFrame(const Value: TFrame);
begin
if FFrame <> value then
begin
if FFrame <> nil then
begin
FFrame.WindowProc := FOldWinProc;
FFrame := nil;
end;
FFrame := value;
if FFrame <> nil then
begin
FreeNotification(Value);
FOldWinProc := FFrame.WindowProc;
FFrame.WindowProc := FrameWinProc;
end;
end;
end;
end.
So now I just need to overcome the flicker, I tried turning on double
buffering, but that just introduces another problem, checkboxes paint as
black....
I forgot to mention that the flicker happens when the focused control
changes.
does this help? You need to install madCodeHook, though.
unit FixQC3850;
interface
implementation
uses Windows, Forms, madCodeHook;
var FramePaintWindowNextHook : procedure (Self: TFrame; DC: HDC);
procedure FramePaintWindowCallback(Self: TFrame; DC: HDC);
begin
if DC = 0 then
FramePaintWindowNextHook(Self, DC);
end;
type TAnotherFrame = class (TFrame);
initialization
HookCode(@TAnotherFrame.PaintWindow, @FramePaintWindowCallback,
@FramePaintWindowNextHook);
end.
--
www.madshi.net
quality low level Delphi components
extended exception handling
API hooking, DLL injection
undocumented functionality
Don't know, will test it and let you know...
I am afraid that if it does make Top10 in most voted you can forget about
it. Sorry.
best regards
Thomas
Unfortunately it doesn't help.. it causes page controls not to paint
themselves... my frames are hosted by a page control and the page control
becomes completely transparent.
Thanks for trying though!
Oh, I see. My code hooks "TFrame.PaintWindow". But since TFrame has no
own PaintWindow method, actually I'm hooking "TWinControl.PaintWindow".
So my hook shows effect on too many controls. But by changing the "if"
line in my FixQC3850 unit like shown below you should get it working:
if (DC = 0) or (not (Self is TFrame)) then
Nope, same effect.
unit FixQC3850;
interface
implementation
uses Windows, Forms, madCodeHook;
var FramePaintWindowNextHook : procedure (Self: TObject; DC: HDC);
procedure FramePaintWindowCallback(Self: TObject; DC: HDC);
begin
if (DC = 0) or (not (Self is TFrame)) then
FramePaintWindowNextHook(Self, DC);
end;
type TAnotherFrame = class (TFrame);
initialization
HookCode(@TAnotherFrame.PaintWindow, @FramePaintWindowCallback,
@FramePaintWindowNextHook);
end.
--
Make sure you drop a panel on the frame, otherwise you might not see the
original problem, and add XPMan to your uses clause. I'm still seeing this,
if I set a breakpoint on the FramePaintWindowNextHook(Self, DC); line it
never breaks, so that line never gets called.
I think the problem is that the PaintWindow workaround does not tell the
whole story.. there more to it than that.
I saw the original problem. If I remove my unit, the label is invisible.
So my demo project is "correctly" set up.
> I'm still seeing this, if I set a breakpoint on the
> FramePaintWindowNextHook(Self, DC); line it never breaks, so that
> line never gets called.
That's strange. On my PC that line gets called and the label gets
visible. Here's my project:
It contains all sources together with two exes, one with the hook and
one without the hook. In the first exe the label is visible, in the
second it's not visible.
> I think the problem is that the PaintWindow workaround does not tell the
> whole story.. there more to it than that.
That might be. Could you upload a little demo project with which we can
reproduce the problem with your specific component set up? I think I
should be able to find a working fix for you then.
I am remotely following this thread and just tried your two exes. I started
the exe with the hook and could indeed see the label. I then started the exe
without the hook and couldn't see the label, as rightly claimed. The
position and dimensions of the second exe are the same as the first one.
Therefore, it covered up the exe with the hook. Now, that's where things are
getting interesting: I moved the exe without the hook, so the one with the
hook can be seen... Well, at that point, the label is not visible anymore...
Cheers, Alan.
Ok, found the problem, I still had the Self parameter declared as TFrame
instead of TObject.
It appears to solve the problem quite well in the test app, however in my
real app it doesn't work, the callback function is never called. Still
trying to figure out why..
To which module have you linked my fix unit? I guess you linked it to
the exe, right? Is the exe compiled with using runtime packages, too?
Does it use the very same runtime packages (rtl70.bpl + vcl70.bpl) which
all of your other modules (dlls + bpls) are using?
If the exe is not compiled with runtime packages, then my unit only
fixes the TFrame components of your exe, but not those of the other
modules. That's the only explanation I have right now. But I'm only
guessing, of course...
I linked it to the exe, since that's where the frames are being
instanciated. I am using runtime packages which could be the problem, I'm
going to try some more tests with demo packages and see what happens.
To say the least, indeed... Just for information, I am running WinXP Pro
with all the updates. Otherwise, I just tried it one more time, trying to
maximise/minimise/etc. and I stand by my previous message...
Cheers, Alan.
Same with me!
However, I'm using a patched uxtheme.dll, so that I can directly use 3rd
party themes. But I don't really think that this would make a
difference.
> Otherwise, I just tried it one more time, trying to maximise/
> minimise/etc. and I stand by my previous message...
#8-O
That's me being confused.
Well, I tried with runtime packages and without and it both worked for
me. So I'm not sure what the problem is.
If you have something with which I can reproduce the problem on my PC,
you can send it to me (if you like).
So did I, and in a test app it worked fine.
> If you have something with which I can reproduce the problem on my PC,
> you can send it to me (if you like).
Ok, I'm still trying to narrow this down, it's hooking the function ok, in
that HookCode returns true, and the FramePaintWindowNextHook is assigned,
but the callback is never called. Strange.
Is there a source level patch to the VCL that would fix the problem? If
there is then maybe an alternative would be to patch the code at run-
time (in memory after the Delphi BPL's have loaded).
Marc
See the rest of the thread and the posts by madshi, that's exactly what we
are doing now... works well in a test app but not in my real project.. still
working on it..
That's really strange. Do you use some special TFrame components which
have their own PaintWindow method - after all it's a virtual method? Or
do you still subclass the frames? It seems that your frames somehow
don't end up in TWinControl.PaintWindow. If HookCode returns true,
there's almost no way that your code can run through TFrame.PaintWindow
(= TWinControl.PaintWindow) without that the hook callback is fired. So
it really seems obvious that your frames do NOt run through
TWinControl.PaintWindow. Now we have to find the reason for that.
I haven't been looking at the details but from what I have seen you are
trying to hook the method in every single frame created. I was thinking
about making a change once to the code for TFrame or TGraphic control.
Marc
What I don't understand is that the hook is actually patching
TWinControl.PaintWindow remember (because TFrame doesn't override it), so no
matter what that function should get called for all the other win controls
in the application.
As for my frames, they are just standard TFrame descendants, which implement
a particular interface (not that I think that would cause any problems). The
frame units are all in runtime packages, but I tried that with the sample
app and that worked fine..... stumped!
Ok, looks like we finally have this bug worked around. What I did was
modifiy the unit like this :
unit FixQC3850;
interface
procedure InitFixQC3850;
implementation
uses Windows, Forms, madCodeHook;
var FramePaintWindowNextHook : procedure (Self: TObject; DC: HDC);
var
isInitOk : boolean = false;
procedure FramePaintWindowCallback(Self: TObject; DC: HDC);
begin
if (DC = 0) or (not (Self is Forms.TFrame)) then
FramePaintWindowNextHook(Self, DC);
end;
type
TAnotherFrame = class(Forms.TFrame);
procedure InitFixQC3850;
begin
if not isInitOk then
isInitOK := HookCode(@TAnotherFrame.PaintWindow,
@FramePaintWindowCallback, @FramePaintWindowNextHook);
end;
end.
and then called the InitFixQC3850 function in my mainform's formactivate
event handler. Strange that this worked, must be some sort of order of
events problem.
Anyway, thanks for your persistance Mathias, looks like the work around is
working well so far :)
> I am afraid that if it does make Top10 in most voted you can forget
> about it.
I'm glad you don't make the decisions, then.
-Craig
--
Craig Stuntz [TeamB] . Vertex Systems Corp. . Columbus, OH
Delphi/InterBase Weblog : http://delphi.weblogs.com
IB 6 versions prior to 6.0.1.6 are pre-release and may corrupt
your DBs! Open Editon users, get 6.0.1.6 from http://mers.com
Exactly - and it does in the test project, that's why the PageControl
disappeared with my first patch try... :-)
<sigh>
Phew! It was exciting to follow!
And you saved Borland an update <g, d&r>
--
Ingvar Nilsen
Well, congratulations! You are close to finding the problem. All you
have to do now is to narrow it down by removing code piece by piece.
--
Ingvar Nilsen
Glad you enjoyed it.. I'm almost bald after messing with this :)
> And you saved Borland an update <g, d&r>
No way.. that's just one of many bugs resolved... oh, and it requires a
third party product to fix the bug.. not ideal for most people.
Yipih-yey!
> What I did was modifiy the unit like this [...]
> and then called the InitFixQC3850 function in my mainform's formactivate
> event handler. Strange that this worked, must be some sort of order of
> events problem.
Huh, I'm not really understanding why this makes a difference. But hey,
it's great that you seemingly got it solved!
> Anyway, thanks for your persistance Mathias
I'm glad to have been of service... :-)
> Ok, looks like we finally have this bug worked around.
Please post this as a workaround in QC, if you haven't already.
Thanks!
-Craig
--
Craig Stuntz [TeamB] . Vertex Systems Corp. . Columbus, OH
Delphi/InterBase Weblog : http://delphi.weblogs.com
How to ask questions the smart way:
http://www.catb.org/~esr/faqs/smart-questions.html
Somehow it may become the rule, not the exception..
--
Ingvar Nilsen
Before I dig out my code, is this workaround likely to fix QC 4167?
"Dave Nottage (TeamB)" <dav...@nospamola.smartchat.net.au> wrote in message
news:3f5e...@newsgroups.borland.com...
> Vincent Parrett (Atozed Software) wrote:
> > Does anyone have any usuable work arounds for QC#3850 -
> > "TGraphicControl descendants invisible in frames with XP Manifest"
> > (and the other related reports to do with parentbackground & themes).
>
> I've made the workaround listed for QC3850 visible. It seems to work for a
> simple test app, eg:
>
> unit Unit2;
>
> interface
>
> uses
> Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
> Dialogs, StdCtrls, ExtCtrls;
>
> type
> TFrame2 = class(TFrame)
> Panel1: TPanel;
> Label1: TLabel;
> private
> { Private declarations }
> protected
> procedure PaintWindow(DC: HDC); override;
> public
> { Public declarations }
> end;
>
> implementation
>
> {$R *.dfm}
>
> { TFrame2 }
>
> procedure TFrame2.PaintWindow(DC: HDC);
> begin
> if DC = 0 then
> inherited;
> end;
>
> end.
>
> Although of course with this method you'd need to add code like this for
> each frame. Please let me know whether this helps.
>
> --
> Dave Nottage (TeamB)
>
>
Where's Petr Vones when you need him? <g>
--
Dave Nottage (TeamB)
Already done.
Possible, see the other work around posted in the other part of this thread
with myself and madshi
Tx much.
--
John Kaster, Borland Developer Relations, http://bdn.borland.com
$1280/$50K: http://homepages.borland.com/jkaster/tnt/thanks.html
Make a wish: http://qc.borland.com * Get source
http://codecentral.borland.com
I'm not finding this in QC. Where do I have to look? Thnx!
look in the status bar in QC when on 3850, it should say "1 unprocessed work
around", I guess that means someone (ie a sysop) has to make it visible.
Another thing I didn't know about QC... :-)
Now visible (instead of the old one).
--
Dave Nottage (TeamB)
Actually, the old one also had some usefull information for the R&D team
when they finally get around to fixing the problem.. so I hope it's not been
deleted.
Not deleted, but I don't think it's possible to see both. Jeff? <g>
Having said that, QA and R&D should be able to access the info if they so
desire.
--
Dave Nottage (TeamB)
> Not deleted, but I don't think it's possible to see both. Jeff? <g>
Yes it is, if both are approved.
-Craig
--
Craig Stuntz [TeamB] . Vertex Systems Corp. . Columbus, OH
Delphi/InterBase Weblog : http://delphi.weblogs.com
InterBase Performance Monitor -- Analyze and control your IB7
server: http://delphi.weblogs.com/IBPerformanceMonitor
Whoops.. I should have scrolled down further <g>
Both are now visible.
--
Dave Nottage (TeamB)
--
Luigi D. Sandon
"Dave Nottage (TeamB)" wrote:
>
> Craig Stuntz [TeamB] wrote:
> >> Not deleted, but I don't think it's possible to see both. Jeff? <g>
> >
> > Yes it is, if both are approved.
>
> Whoops.. I should have scrolled down further <g>
>
I changed the workaround logic about 8 months ago to allow for multiple approved
workarounds just for cases like this.
> Both are now visible.
>
> --
> Dave Nottage (TeamB)
--
Jeff Overcash (TeamB)
(Please do not email me directly unless asked. Thank You)
If there is somebody up there could they throw me down a line. Just a
little helping hand just a little understanding. Just some answers to the
questions that surround me now. If there's somebody up there could
they throw me down a line. (Fish)
"Noone is processing them" is false, especially given that 3850's have been
processed. You mean that not all have been processed. FWIW, I'm processing
them where they have been verified.
I've now processed the workarounds for 2002.
--
Dave Nottage (TeamB)
> Another entry, 2002 has two submitted workarounds who may help people to
> work better (it's the XP DLL debugging problem) but noone is processing
> them.
One has been processed now, and is visible.
--
Cheers,
David Clegg
dclegg_at_ebetonline_dot_com
{$IFDEF Alessandro}Italian{$ELSE}French{$ENDIF} is the language of love.
For everything else there's Delphi^h^h^h^h^h^h C#.
At the pub, of course!
--
-Brion
Team JEDI, 2001 Spirit of Delphi Award Winners
http://www.delphi-jedi.org
Fresno Area Delphi Users Group
http://groups.yahoo.com/group/FresnoDelphi
I'm back :-)
What did you need, Dave ? <g>
Petr.