TImage Not Showing up - delphi

When dropping this component onto the form, The TImage is not showing the map image (hexagons) Until i drag the component around on the form , Then it will show it until i stop dragging it around on the form. (this is all in desgin mode). How do i make it show all the time? not when just dragging it.
type
THexMap = Class(TScrollingWinControl)
Constructor
Constructor THexMap.Create(AOwner: Tcomponent);
begin
inherited Create(AOwner);
Width := DEFAULT_MAP_WIDTH;
Height := DEFAULT_MAP_HEIGHT;
FCanvas := timage.Create(self);
tempMap := timage.Create(self);
fcanvas.Parent := self;
tempmap.Parent := self;
fCanvas.Width := DEFAULT_MAP_WIDTH;
fCAnvas.Height := DEFAULT_MAP_WIDTH;
{ Set intial property values for component }
//create map
MakeSolidMap;
end;
MakeSolidMap
Procedure THexMap.MakeSolidMap;
var
p0 : TPoint;
looprow,Loopcol : integer;
begin
TempMap.width := ((HexColumns-1) * round((1.5 * HexRadius))) + (2 * hexRadius);
TempMap.height := ((HexRows) * (2 * rise)) + rise;
With TempMap.Canvas do
begin
{set Background color}
brush.Color := BackColor;
fillrect(rect(0,0,TempMap.Width,TempMap.Height));
{draw Hex's left to right / top to bottom}
for looprow := 1 to HexRows do
begin
for loopcol := 1 to HexColumns do
begin
{compute center coords}
p0 := ConvertCoords(Point(LoopCol,LoopRow),ptROWCOL);
{draw the hex}
DrawSolidHex(Tempmap,bsSolid,hexColor,psSolid,LineColor,P0.X,p0.Y,hexRadius,hex3d);
end;
end;
end;
end;
DrawSoildHex
procedure THexMap.DrawSolidHex(Target: timage;
FillStyle: TBrushStyle;
FillColor: TColor;
LineStyle: TPenStyle;
LineColor: TColor;
x: Integer;
y: Integer;
Radius: Integer;
button: Boolean);
var
p0,p1,p2,p3,p4,p5,p6:TPoint;
begin
p0 := Point(x,y);
{compute each point based on hex center}
p1.X := p0.X - round(Radius /2);
p1.Y := p0.Y - rise;
p2.X := p0.X + round(Radius/2);
p2.Y := p1.Y;
p3.X := p0.X + Radius;
p3.Y := p0.Y;
p4.X := p2.X;
p4.Y := p0.Y + rise;
p5.X := p1.X;
p5.Y := p4.Y;
p6.X := p0.X - Radius;
p6.Y := p0.Y;
{set color / style of lines}
target.canvas.Pen.Color := LineColor;
target.canvas.Pen.Style := LineStyle;
{set color / style of hex}
target.canvas.Brush.Color := FillColor;
Target.canvas.Brush.Style := FillStyle;
{draw the hex}
target.canvas.Polygon([p1,p2,p3,p4,p5,p6]);
{if desired, draw the boarder for the hex}
if button = true then
begin
with target.canvas do
begin
pen.Mode :=pmCopy;
pen.Color :=clWhite;
moveto(p5.X+1,p5.Y-1);
lineto(p6.X+1,p6.Y);
lineto(p1.X+1,p1.Y+1);
lineto(p2.X-1,p2.Y+1);
pen.Color :=clBlack;
lineto(p3.X-1,p3.Y);
lineto(p4.X-1,p4.Y-1);
lineto(p5.X+1,p5.Y-1);
end;
end;
invalidate;
end;
WndProc
procedure THexMap.WndProc(var Message: TMessage);
const
DISCARD_CURRENT_ORIGIN = nil;
var
R : TRect;
PS : PAINTSTRUCT;
begin
if Message.Msg = WM_PAINT then
begin
if GetUpdateRect( Handle, nil, false ) then
begin
BeginPaint( Handle, PS );
try
R := PS.rcPaint;
bitblt(fCanvas.Canvas.Handle, R.Left, R.Top, R.Width, R.Height, TempMap.Canvas.Handle, R.Left+FOffset.X, R.Top+FOffset.Y, SRCCOPY);
finally
EndPaint( Handle, PS );
end;
end
else
inherited;
end
else
inherited;
end;

Nothing shows because you have taken over painting the control by handing WM_PAINT. And in your handling of WM_PAINT you do not paint anything to the device context returned by BeginPaint. You do not call the inherited handler which would call Paint and then paint children. Hence nothing appears in your control.
It seems to me that you need to decide to either use visual controls and let the VCL paint them, or paint your control yourself. You are currently attempting to do both but achieving neither!
I cannot suggest a fix because I've really no idea what you are doing. I don't understand why you have visual controls and override the paint message handler. To go forward you'll need to pick one approach or the other.

Related

Combination of Canvas.TransparentColor and Canvas.Draw with Opacity

i want to draw a bitmap on a canvas with opacity where the bitmap has a transparent color.
i could create a bitmap with transparent color and draw it to a
canvas i could create a bitmap and draw it to a canvas with opacity
but i couldn't combine it. if i combine it the opacity is ignored.
here is the code i wrote:
procedure TForm1.FormPaint(Sender: TObject);
var b1,b2:TBitmap;
begin
// Example how it opacity works:
b1 := TBitmap.Create;
b1.SetSize(20,20);
b1.Canvas.Brush.Color := clBlue;
b1.Canvas.Rectangle(0,0,20,20);
Canvas.Draw(10,10,b1,$ff); // Works
Canvas.Draw(40,10,b1,$66); // Works
// I need it in combination with TransparentColor:
b2 := TBitmap.Create;
// next 3 lines are different from above
b2.Transparent := true;
b2.TransparentColor := clFuchsia;
b2.Canvas.Brush.Color := clFuchsia;
b2.SetSize(20,20);
b2.Canvas.Brush.Color := clBlue;
b2.Canvas.Ellipse(0,0,20,20);
Canvas.Draw(10,40,b2,$ff); // Works (full opacity)
Canvas.Draw(40,40,b2,$66); // Ignores the $66 Opacity
b1.Free;
b2.Free;
end;
produces:
how could i draw (f.e. a blue circle) with transparent background and just 40% opacity?
i would prefere a solution without direct winapi (like bitblt, ...) if possible.
i tried a few hacks like bitshifting a alpha channel to a TColor value but it didn't work.
here i what i tried:
procedure TForm1.FormPaint(Sender: TObject);
var b:TBitmap;
begin
b := TBitmap.Create;
b.PixelFormat := pf32bit;
b.AlphaFormat := afDefined;
b.Canvas.Brush.Color := 0 and ($ff shl 32); // Background Transperency
b.SetSize(20,20);
b.Canvas.Brush.Color := clBlue + (($ff-$66) shl 32);
b.Canvas.Ellipse(0,0,20,20);
Canvas.Draw(10,10,b);
b.Free;
end;
produces:
thanks in advance!
EDIT: my system: delphi xe 5 on windows 7 64bit (but using the 32bit compiler)
What happens can be seen in procedure TBitmap.DrawTransparent in the unit Graphics.
If the property of the image is set to transparent as show for b2 in your example the Bitmap will be drawn with
Graphics.TransparentStretchBlt which is using StretchBlt with differnt masks to draw the image and is not able to use the alpha channel.
A not tranparent Bitmap , your b1, will be draw with
AlphaBlend.
To reach your goal you might use another bitmap b2, set the Alphachannel to 0, paint b2 with opacity $66 on b3, set set the Alphachannel to 255 for every pixel which is clFuchsia in b2 and then paint this bitmap with the desired opacity
type
pRGBQuadArray = ^TRGBQuadArray;
TRGBQuadArray = ARRAY [0 .. 0] OF TRGBQuad;
TRefChanel=(rcBlue,rcRed,rcGreen);
procedure SetBitmapAlpha(ABitmap: TBitMap; Alpha: Byte);
var
pscanLine32: pRGBQuadArray;
nScanLineCount, nPixelCount : Integer;
begin
with ABitmap do
begin
PixelFormat := pf32Bit;
HandleType := bmDIB;
ignorepalette := true;
alphaformat := afDefined;
for nScanLineCount := 0 to Height - 1 do
begin
pscanLine32 := Scanline[nScanLineCount];
for nPixelCount := 0 to Width - 1 do
with pscanLine32[nPixelCount] do
begin
rgbReserved := Alpha;
end;
end;
end;
end;
procedure AdaptBitmapAlpha(ABitmap,TranspBitmap:TBitmap);
var
pscanLine32,pscanLine32_2: pRGBQuadArray;
nScanLineCount, nPixelCount : Integer;
begin
with ABitmap do
begin
PixelFormat := pf32Bit;
HandleType := bmDIB;
ignorepalette := true;
alphaformat := afDefined;
for nScanLineCount := 0 to Height - 1 do
begin
pscanLine32 := Scanline[nScanLineCount];
pscanLine32_2 := TranspBitmap.Scanline[nScanLineCount];
for nPixelCount := 0 to Width - 1 do
with pscanLine32[nPixelCount] do
begin
// all picels with are not clFuchsia in the transparent bitmap
if NOT ((pscanLine32_2[nPixelCount].rgbBlue=255) AND (pscanLine32_2[nPixelCount].rgbRed=255) AND (pscanLine32_2[nPixelCount].rgbGreen=0) ) then
begin
rgbReserved := 255;
end
else
begin
rgbBlue := 0;
rgbRed := 0;
rgbGreen := 0;
end;
end;
end;
end;
end;
procedure TAForm.FormPaint(Sender: TObject);
var b1,b2,b3:TBitmap;
BF: TBlendFunction;
begin
// Example how it opacity works:
b1 := TBitmap.Create;
b1.SetSize(20,20);
b1.Canvas.Brush.Color := clBlue;
b1.Canvas.Rectangle(0,0,20,20);
Canvas.Draw(10,10,b1,$ff); // Works
Canvas.Draw(40,10,b1,$66); // Works
// I need it in combination with TransparentColor:
b3 := TBitmap.Create;
b3.PixelFormat := pf32Bit;
b2 := TBitmap.Create;
b2.PixelFormat := pf32Bit;
// next 3 lines are different from above
b2.Transparent := true;
b2.TransparentColor := clFuchsia;
b2.Canvas.Brush.Color := clFuchsia;
b2.SetSize(20,20);
b2.Canvas.Brush.Color := clBlue;
b2.Canvas.Ellipse(0,0,20,20);
Canvas.Draw(10,40,b2,$ff); // Works (full opacity)
b3.SetSize(20,20);
SetBitmapAlpha(b3,0);
b3.Canvas.Draw(0,0,b2,$66);
AdaptBitmapAlpha(b3,b2);
Canvas.Draw(40,40,b3,$66);
b1.Free;
b2.Free;
b3.Free;
end;
thanks to bummi (accepted answer)!
i put his solution in a class helper. here is the code if anybody need it:
unit uBitmapHelper;
interface
uses
Vcl.Graphics;
type
TBitmapHelper = class Helper for TBitmap
private
type
TRgbaRec = packed record
r,g,b,a:Byte;
end;
PRgbaRec = ^TRgbaRec;
PRgbaRecArray = ^TRgbaRecArray;
TRgbaRecArray = array [0 .. 0] of TRgbaRec;
public
procedure TransparentMaskedDraw(ACanvas:TCanvas;AX:Integer;AY:Integer;AMask:TColor;AOpacity:Byte);
end;
implementation
{ TBitmapHelper }
procedure TBitmapHelper.TransparentMaskedDraw(ACanvas:TCanvas;AX,AY:Integer;AMask:TColor;AOpacity:Byte);
var i,j:Integer;
line1,line2:PRgbaRecArray;
mask:PRgbaRec;
tmp:TBitmap;
begin
mask := #AMask;
tmp := TBitmap.Create;
tmp.SetSize(self.Width,self.Height);
tmp.PixelFormat := pf32Bit;
tmp.HandleType := bmDIB;
tmp.IgnorePalette := true;
tmp.AlphaFormat := afDefined;
for i := 0 to tmp.Height - 1 do begin
line1 := tmp.Scanline[i];
for j := 0 to tmp.Width - 1 do begin
line1[j].a := 0;
end;
end;
tmp.Canvas.Draw(0,0,self,AOpacity);
for i := 0 to tmp.Height - 1 do begin
line1 := tmp.ScanLine[i];
line2 := self.ScanLine[i];
for j := 0 to tmp.Width - 1 do begin
if not((line2[j].r = mask.r) and (line2[j].g = mask.g) and (line2[j].b = mask.b)) then begin
line1[j].a := $ff;
end else begin
line1[j].r := 0;
line1[j].g := 0;
line1[j].b := 0;
end;
end;
end;
ACanvas.Draw(AX,AY,tmp,AOpacity);
tmp.Free;
end;
end.
The oldest answer is fine, please find some easy reshuffle.
This example also shows how to put one png-image with opacity on another by respecting the transparency.
procedure TForm2.FormCreate(Sender: TObject);
//define your own transparent color by setting RGB-values
const cTransR=255; cTransG=255; cTransB=255;
clTrans= $10000*cTransB + $100*cTransG + cTransR;
var bmp1,bmp2:TBitmap;
pngTemp: TPngImage;
I:integer;
procedure SetAlphaTransparent(VAR LBitmap:TBitmap);
type TRGBQuadArray = ARRAY [0..0] OF TRGBQuad;
var I, J: integer;
LscanLine32:^TRGBQuadArray;
begin
// I found no other way than scanning pixel by pixel to recover default opacity
for I := 0 to LBitmap.Height - 1 do begin
LscanLine32:=LBitmap.ScanLine[I];
for J := 0 to LBitmap.Width - 1 do
with LscanLine32[J] do
if NOT((rgbRed=cTransR)AND(rgbGreen=cTransG)AND(rgbBlue=cTransB)) then
rgbReserved := 255; // make pixel visible, since transparent is default
end;
end;
Procedure SetAlphaProperty(Var LBitmap:TBitmap; LWidth, LHeight:integer);
begin
// You will need a different format Bitmap to allow alpha values
LBitmap.PixelFormat := pf32Bit;
LBitmap.HandleType := bmDIB;
LBitmap.alphaformat := afDefined;
LBitmap.Canvas.Brush.Color := clTrans;
LBitmap.SetSize(LWidth,LHeight);
end;
begin
// create any background on your Form, by placing IMG:Timage on the From
pngTemp := TPngImage.Create;
pngTemp.LoadFromFile( GetCurrentDir()+'\figure1.png' );
IMG.Canvas.Draw((IMG.Width-pngTemp.Width) div 2, // fit png into the center
(IMG.Height-pngTemp.Height) div 2,pngTemp);
pngTemp.Free;
// First example how it opacity works with transparency
bmp1 := TBitmap.Create;
SetAlphaProperty(bmp1,35,35);
// a circle has a surrouding area, to make transparent
bmp1.Canvas.Brush.Color := clBlue;
bmp1.Canvas.Ellipse(5,5,30,30);
SetAlphaTransparent(bmp1);
// show some circles with different opacity
for I := 0 to 7 do
IMG.Canvas.Draw(I*40-30,10,bmp1,(8-I)*32);
bmp1.Free;
// Another example using a different png-file
bmp2 := TBitmap.Create;
SetAlphaProperty(bmp2,Img.Width,Img.Height);
// load a transparent png-file and put it into the alpha bitmap:
pngTemp := TPngImage.Create;
pngTemp.LoadFromFile( GetCurrentDir()+'\figure2.png' );
pngTemp.Transparent := true;
bmp2.Canvas.Draw((bmp2.Width-pngTemp.Width) div 2,// fit png into the center
(bmp2.Height-pngTemp.Height) div 2,pngTemp);
pngTemp.Free;
// draw the second image with transparancy and opacity onto the first one
SetAlphaTransparent(bmp2);
IMG.Canvas.Draw(0,0,bmp2,$66);
bmp2.Free;
end;

TTreeView custom draw item width

I use the OnCustomDrawItem event to draw a TTreeView like this :
Here is my code :
procedure Tform1.trvArbreCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
var
vRect : TRect;
vBmp : TBitmap;
vBmpRect : TRect;
vTreeView : TTreeView;
vBarreInfo : TScrollInfo;
vDeltaX : Integer;
begin
DefaultDraw := False;
vTreeView := TTreeView(Sender);
vRect := Node.DisplayRect(False);
vBmp := TBitmap.Create();
FillChar(vBarreInfo, SizeOF(vBarreInfo), 0);
vBarreInfo.cbSize := SizeOf(vBarreInfo);
vBarreInfo.fMask := SIF_RANGE or SIF_POS;
if GetScrollInfo(trvArbre.Handle, SB_HORZ, vBarreInfo) then
begin
if vBarreInfo.nMax > vRect.Right - vRect.Left then
begin
vBmp.Width := vBarreInfo.nMax + 1;
vBmp.Height := vRect.Bottom - vRect.Top;
vDeltaX := vBarreInfo.nPos;
end
else
begin
vBmp.Width := vRect.Right - vRect.Left;
vBmp.Height := vRect.Bottom - vRect.Top;
vDeltaX := 0;
end;
end
else
begin
vBmp.Width := vRect.Right - vRect.Left;
vBmp.Height := vRect.Bottom - vRect.Top;
vDeltaX := 0;
end;
vBmpRect := Rect(0, 0, vBmp.Width, vBmp.Height);
if cdsSelected in State then
begin
vBmp.Canvas.Brush.Color := cMenuDownFond;
vBmp.Canvas.Pen .Color := cMenuDownBordure;
end
else if cdsHot in State then
begin
vBmp.Canvas.Brush.Color := cMenuSurvolFond;
vBmp.Canvas.Pen .Color := cMenuSurvolBordure;
end
else
begin
vBmp.Canvas.Brush.Color := clWhite;
vBmp.Canvas.Pen .Color := clwhite;
end;
vBmp.Canvas.Rectangle(vBmpRect);
vBmpRect.Left := vBmpRect.Left + 3;
vBmpRect.Left := vBmpRect.Left + (Node.Level * vTreeView.Indent);
if Node.StateIndex >= 0 then
begin
vTreeView.StateImages.Draw(vBmp.Canvas, vBmpRect.Left, vBmpRect.Top, Node.StateIndex);
end;
vBmpRect.Left := vBmpRect.Left + 18;
vTreeView.Images.Draw(vBmp.Canvas, vBmpRect.Left, vBmpRect.Top, Node.ImageIndex);
vBmpRect.Left := vBmpRect.Left + 18 + 3;
vBmp.Canvas.Font := vTreeView.Font;
DrawText
(
vBmp.Canvas.Handle,
PChar(Node.Text),
Length(Node.Text),
vBmpRect,
DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_NOPREFIX or DT_END_ELLIPSIS
);
BitBlt
(
Sender.Canvas.Handle,
vRect.Left,
vRect.Top,
vRect.Right - vRect.Left,
vRect.Bottom - vRect.Top,
vBmp.Canvas.Handle,
vDeltaX,
0,
SRCCOPY
);
FreeAndNil(vBmp);
end;
My problem is that the node "My last node wich is not too long" is not too long to justify the presence of the horizontal scrollbar.
When I set DefaultDraw to true I obtain :
It seems that the width of the node is computed with a font I don't use.
I tried to change the font of the canvas, to use Windows API, to use the OnAdvancedCustomDrawItem with no result.
Thanks.
I use Delphi 7. I copied ComCtrls.pas in the folder of my application. I changed procedure TCustomTreeView.CNNotify(var Message: TWMNotify);. Line 8979 from Result := Result or CDRF_SKIPDEFAULT to Result := Result or CDRF_SKIPDEFAULT; and I commented line 8980 else if FCanvasChanged then in order to simulate DefaultDraw=True and FCanvasChanged even if I set DefaultDraw to False in event et don't change font. After a lot of tests, I don't see any caveats.

Left aligned Tabsheets on JvgPageControl Delphi + Vcl Styles Enabled Issue

On Windows default appearance the tabsheet caption are showed in horizontal (left to right 1) and with the VCL styles enabled they are displayed in vertical (down to top[2]). How I can fix this on Delphi XE5?
Detail: I'm using the JvgPageControl component, from JEDI-VCL 3.58.
I want to create an similar interface of DisplayFusion welcome screen [3]. Suggestions are welcome!
Images:
Thanks in advance!
The TJvgPageControl uses the same vcl style hook (TTabControlStyleHook) of the TPageControl control, so you must create a new style hook inherited from the TTabControlStyleHook and override the DrawTab method.
Check this basic implementation for the new style hook
type
TTabControlStyleHookExt = class(TTabControlStyleHook)
protected
procedure DrawTab(Canvas: TCanvas; Index: Integer); override;
end;
TCustomTabControlClass = class(TCustomTabControl);
{ TTabControlStyleHookExt }
procedure TTabControlStyleHookExt.DrawTab(Canvas: TCanvas; Index: Integer);
var
R, LayoutR, GlyphR: TRect;
ImageWidth, ImageHeight, ImageStep : Integer;
LDrawState: TThemedTab;
LDetails: TThemedElementDetails;
ThemeTextColor: TColor;
FImageIndex: Integer;
begin
if TabPosition <> tpLeft then
begin
inherited ;
exit;
end;
if (Images <> nil) and (Index < Images.Count) then
begin
ImageWidth := Images.Width;
ImageHeight := Images.Height;
ImageStep := 3;
end
else
begin
ImageWidth := 0;
ImageHeight := 0;
ImageStep := 0;
end;
R := TabRect[Index];
if R.Left < 0 then Exit;
if Index = TabIndex then
Dec(R.Left, 2)
else
Dec(R.Right, 2);
Canvas.Font.Assign(TCustomTabControlClass(Control).Font);
LayoutR := R;
if Index = TabIndex then
LDrawState := ttTabItemLeftEdgeSelected
else if (Index = HotTabIndex) and MouseInControl then
LDrawState := ttTabItemLeftEdgeHot
else
LDrawState := ttTabItemLeftEdgeNormal;
LDetails := StyleServices.GetElementDetails(LDrawState);
StyleServices.DrawElement(Canvas.Handle, LDetails, R);
{ Image }
if Control is TCustomTabControl then
FImageIndex := TCustomTabControlClass(Control).GetImageIndex(Index)
else
FImageIndex := Index;
if (Images <> nil) and (FImageIndex >= 0) and (FImageIndex < Images.Count) then
begin
GlyphR := LayoutR;
GlyphR.Bottom := GlyphR.Bottom - ImageStep;
GlyphR.Top := GlyphR.Bottom - ImageHeight;
LayoutR.Bottom := GlyphR.Top;
GlyphR.Left := GlyphR.Left + (GlyphR.Right - GlyphR.Left) div 2 - ImageWidth div 2;
if StyleServices.Available then
StyleServices.DrawIcon(Canvas.Handle, LDetails, GlyphR, Images.Handle, FImageIndex);
end;
{ Text }
if StyleServices.GetElementColor(LDetails, ecTextColor, ThemeTextColor) then
Canvas.Font.Color := ThemeTextColor;
//use the top tab style to draw the text
if Index = TabIndex then
LDetails := StyleServices.GetElementDetails(ttTabItemSelected)
else
if (Index = HotTabIndex) and MouseInControl then
LDetails := StyleServices.GetElementDetails(ttTabItemHot)
else
LDetails := StyleServices.GetElementDetails(ttTabItemNormal);
DrawControlText(Canvas, LDetails, Tabs[Index], LayoutR, DT_VCENTER or DT_CENTER or DT_SINGLELINE or DT_NOCLIP);
end;
Then register the new style hook like this
initialization
TStyleEngine.RegisterStyleHook(TJvgPageControl, TTabControlStyleHookExt);

How to resize Popup Window dynamically at runtime?

I try to create a custom Combobox control that popups a Treeview.
Everything looks fine.
But when i try to add runtime resize functionality to that control, the popup window (Treeview) just move and won't change its size.
Any suggestion would be appreciated.
Snippets for Popup Window :
On Create :
ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable, csDoubleClicks];
On Create Params :
begin
inherited CreateParams(Params);
with Params do
begin
Style := Style or WS_POPUP or WS_VSCROLL or WS_BORDER;
ExStyle := WS_EX_TOOLWINDOW;
AddBiDiModeExStyle(ExStyle);
//WindowClass.Style := CS_SAVEBITS; {this would prevent ondoubleclick event}
end;
On Mouse Move :
var
ARect, RR: TRect;
DragStyle: TDragStyle;
Procedure SetDragStyle(ds:TDragStyle; c:TCursor);
begin
FDragStyle:=ds;
Cursor:=c;
end;
begin
inherited;
FMouseMoveSelected := GetNodeAt(x, y);
if FDragged then begin
case FDragStyle of
dsSizeLeft :begin
SetWindowPos(Handle, HWND_TOP, Left+(x-FDragPos.X), Top, Width, Height,
SWP_NOACTIVATE or SWP_SHOWWINDOW);
//Left:=Left+(x-FDragPos.X); {alternate code that doesn't work either}
end;
end;
FDragPos:=Point(x,y);
end else begin
SetDragStyle(dsMove,crDefault);
ARect := GetClientRect;
RR:=ARect;
InflateRect(RR,-2,-2);
if (x>=0) and (x<=Width) and (y>=0) and (y<=Height) and (not PtInRect(RR,Point(x,y))) then begin
if (x<=RR.Left) then begin
//if (y<=RR.Top) then SetDragStyle(dsSizeTopLeft,crSizeNWSE)else
if (y>=RR.Bottom) then SetDragStyle(dsSizeBottomLeft,crSizeNESW)
else SetDragStyle(dsSizeLeft,crSizeWE);
end else if (x>=RR.Right) then begin
//if (y<=RR.Top) then SetDragStyle(dsSizeTopRight,crSizeNESW) else
if (y>=RR.Bottom) then SetDragStyle(dsSizeBottomRight,crSizeNWSE)
else SetDragStyle(dsSizeRight,crSizeWE);
end else begin
//if (y<=RR.Top) then SetDragStyle(dsSizeTop,crSizeNS) else
if (y>=RR.Bottom) then SetDragStyle(dsSizeBottom,crSizeNS)
else SetDragStyle(dsMove,crDefault);
end;
end;
end;
end;
end;
On Mouse Down :
begin
inherited;
if FDragStyle<>dsMove then begin
FDragPos:=point(x,y);
FDragged:=true;
end;
end;
On Mouse Up :
begin
inherited;
FDragged:=false;
end;
You're mixing client coordinates with screen coordinates in the SetWindowPos call. That's because you're floating a window that's not supposed to float and the VCL has no knowledge of it. When you refer to its Left, the VCL returns a coordinate relative to its parent, probably the form. Also don't change the point you saved while you started to drag during the drag (that being FDragPos):
procedure TPanel.MouseMove(Shift: TShiftState; X, Y: Integer);
var
ARect, RR: TRect;
DragStyle: TDragStyle;
Procedure SetDragStyle(ds:TDragStyle; c:TCursor);
begin
FDragStyle:=ds;
Cursor:=c;
end;
var
DragOffset: Integer;
begin
inherited;
FMouseMoveSelected := GetNodeAt(x, y);
if FDragged then begin
case FDragStyle of
dsSizeLeft:
begin
DragOffset := X - FDragPos.X;
winapi.windows.GetWindowRect(Handle, ARect);
SetWindowPos(Handle, HWND_TOP,
ARect.Left + DragOffset,
ARect.Top,
ARect.Right - ARect.Left - DragOffset,
ARect.Bottom - ARect.Top,
SWP_NOACTIVATE or SWP_SHOWWINDOW);
//Left:=Left+(x-FDragPos.X); {alternate code that doesn't work either}
end;
end;
// FDragPos:=Point(x,y); // do not change drag origin while you're dragging
end else begin
..

AnimateWindow Slide

I want my form slide down and back to position with slide animation, how to make correct AnimateWinows, if it real for sure ...
void __fastcall TUsers::BitBtn1Click(TObject *Sender)
{
if (!pressed)
{
Height=700;
//AnimateWindow(Handle, 500, AW_CENTER | AW_SLIDE | AW_VER_POSITIVE);
pressed=true;
}
else
{
pressed=false;
//AnimateWindow(Handle, 500, AW_CENTER | AW_SLIDE | AW_VER_NEGATIVE);
Height=425;
}
}
to moderators : here is no mutters Builder or Delphi :)
If you are interested in controlling the animation yourself, here is a sample of code we wrote to accomplish that. It looks and works great. We are sliding Tform1 from the right to the left within a TPanel control on the main form. We ensure that Self.Parent and DoubleBuffered gets set correctly in MyCreate. ShiftLeft and then ShiftRight do the work. We ran into a problem for certain users where the Self.Top was being shifted so we are making sure that Self.Top := 0 with each iteration and when fully shifted. That solved all of the weird issues we were seeing.
Hope this helps!
{
TForm1.MyCreate
---------------------------------------------------------------------------
}
constructor TForm1.MyCreate(AOwner: TComponent);
var
OwnerControl: TWinControl;
begin
inherited Create(AOwner);
if Owner is TWinControl then
begin
OwnerControl := Owner as TWinControl;
Self.Parent := OwnerControl;
end;
Self.Visible := false;
Self.DoubleBuffered := true;
Self.BorderStyle := bsNone;
end;
{
TForm1.ShiftLeft
---------------------------------------------------------------------------
}
procedure TForm1.ShiftLeft;
var
TicksStart: int64;
InitLeftValue: integer;
StartLeftValue: integer;
NewLeftValue: integer;
LeftValueDif: integer;
RemainingTicks: int64;
begin
Self.Top := 0;
Self.Height := Self.Parent.ClientHeight;
Self.Width := Self.Parent.ClientWidth;
InitLeftValue := Self.Parent.Left;
StartLeftValue := Self.Parent.Left + Self.Parent.ClientWidth;
LeftValueDif := StartLeftValue - InitLeftValue;
Self.Left := StartLeftValue;
Self.Visible := true;
TicksStart := GetTickCount();
RemainingTicks := FadeTime;
while RemainingTicks > 0 do
begin
NewLeftValue := (LeftValueDif * RemainingTicks) div FadeTime;
Self.Left := Max(InitLeftValue, NewLeftValue);
Self.Parent.Repaint;
Self.Top := 0;
Self.Repaint;
RemainingTicks := FadeTime - int64(GetTickCount - TicksStart);
end;
if Self.Left > InitLeftValue then
Self.Left := InitLeftValue;
Self.Parent.Repaint;
Self.Top := 0;
Self.Repaint;
end;
{
TForm1.ShiftRight
---------------------------------------------------------------------------
}
procedure TForm1.ShiftRight;
var
TicksStart: int64;
StartLeftValue: integer;
EndLeftValue: integer;
NewLeftValue: integer;
LeftValueDif: integer;
RemainingTicks: int64;
begin
Self.Top := 0;
StartLeftValue := Self.Left;
EndLeftValue := Self.Left + Self.Width;
LeftValueDif := EndLeftValue - StartLeftValue;
TicksStart := GetTickCount();
RemainingTicks := FadeTime;
while RemainingTicks > 0 do
begin
NewLeftValue := (LeftValueDif * (FadeTime - RemainingTicks)) div FadeTime;
Self.Left := Max(StartLeftValue, NewLeftValue);
Self.Parent.Repaint;
Self.Top := 0;
Self.Repaint;
RemainingTicks := FadeTime - int64(GetTickCount - TicksStart);
end;
if Self.Left < EndLeftValue then
Self.Left := EndLeftValue;
Self.Parent.Repaint;
Self.Top := 0;
Self.Repaint;
end;
That's not what AnimateWindow is for. That function hides or shows a window using some animation. Your window is already visible, and you want it to stay visible, so AnimateWindow is not for you.
What you should do instead is make your window successively taller or shorter in a loop until you reach the new desired height.
Check the following link for an answer and a cool demo program.
http://delphi.about.com/od/delphi-tips-2011/qt/hide-slide-fade-away-controls-delphi-form.htm

Resources