I'd like to align an object in X and Y by eye using the mouse to move it into position. I can roll a solution by using various spin controls (or buttons) but it's messy and I got to wondering whether there is a control - like a joystick - that provides 2-axis control using the mouse and fires events at rates which vary depending on its position?
Afaik Jedi (jedi apilib?) had a joystick header too. It is winapi, not COM, so no TLB involved
Try NLDJoystick, an open-source component written by me and based on pure WinAPI (MMSystem.pas). It is downloadable from GitHub.
The interface:
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property AbsCenter;
property AbsMax;
property AbsMin;
property Active default False;
property Advanced default False;
property AxisCount;
property Axises;
property ButtonCount;
property HasPOV;
property ID;
property OnButtonDown;
property OnButtonUp;
property OnMove;
property OnPOVChanged;
property PollingInterval default 40;
property RepeatButtonDelay default 350;
property RepeatMoveDelay default 350;
property SuspendScreensaver default False;
property ThresholdFactor;
Maybe you can make something like that yourself.
Take a panel, and register on Mouse up, down and move events
On MouseDown, set a boolean (fButtonDown) so you know that the mousebutton is pressed and save the X and Y coordinates of the mousepointer.
On MouseMove, check if a button is down (fButtonDown) and move your object. The more your mousecursor is moved from its saved position, the faster you move.
On MouseUp, set fButtonDown to false
The above is very primitive, but should work.
I Googled for "joystick dll" and found countless. You can probably throw one of these into your project and then access its C API from Delphi by simply writing a TLIB header (or whatever it's called, haven't done this in a while) for it.
You may use a DelphiX components. They are wrappers for DirectX and one of them wraps around DirectX joystick interface as far as I remember. It wraps in a Delphi-style so it is easy to use.
Related
I'm trying to create a custom VCL component that can have a custom sound played when clicked. The sound is accessed from a resource DLL.
Question is, the sound is played using Direct X, and for it to be created it need a valid window handle.
My naive initial test was to initialize the sound in the components constructor:
__fastcall TArrayBotButton::TArrayBotButton(TComponent* Owner)
: TBitBtn(Owner),
FSoundID("BUTTON_CLICK_1")
{
initABCoreLib();
HWND hWnd = Application->MainFormHandle;
mSound.Create(FSoundID.c_str(), hWnd);
}
but the above does not work, as the MainFormHandle at this point is NULL. Also, being a component, using the Application variable is probably not safe in the constructor(?).
Any pointers on where to initialize the sound?
Why not just use the button's own HWND instead? TBitBtn is a windowed control. Its HWND is not available in the constructor, but you can (and should) override the button's virtual CreateWnd() method to create the DirectX object, and override the virtual DestroyWnd() method to release it. This way you also account for window recreations during the button's lifetime.
Can someone please explain me which control is better to create custom componens? What is the difference between twincontrol and tcustomcontrol?
Thank you in advance
Can someone please explain me which control is better to create custom componens?
That depends on what kind of component you are making and what its requires are.
Is it visual?
If no, use TComponent.
if yes, does it need its own HWND (input focus, window messages, etc)?
If no, use TGraphicControl.
If yes, does it need to custom paint itself?
if yes, use TCustomControl.
if no, use TWinControl.
What is the difference between twincontrol and tcustomcontrol?
TCustomControl is a TWinControl descendant that adds some additional handling for the WM_PAINT message, on top of what TWinControl does. TCustomControl exposes a public Canvas property that you can draw on. During painting, it enables the csCustomPaint flag in the ControlState property, and then calls a virtual Paint() method that your component can override. So the benefit of TCustomControl is that it makes custom painting a little easier to manage. Nothing more.
I am trying to make a TCard component for a game. What class should I derive it from?
This is for a card game like MTG or yu gi oh. The card should have a blank image, and when created it will load either a front or back view.
If it loads the front view, it will then have to have a few labels (for properties like power/cost/def/text). Cards must be clickable.
type
TCard = class(zzzzzzzzz)
private
Now once that is done, do I have to add anything to the constructor/destructor? Currently I have:
constructor TCard.Create(AOwner: Tcomponent);
begin
inherited Create(AOwner);
end;
{******************************************************************************}
{ Free any resources allocated to component }
destructor TCard.Destroy;
begin
inherited Destroy;
end;
Also I think I added the onclick parts right but not sure. In the published area I have
{Inherited properties}
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnClick;
property OnDblClick;
etc...
It depends on what you want to do, but typically there are two ancestors for visible controls:
TGraphicControl: This is a descendant of TControl that implements a Canvas for you. You can just override the Paint method to start drawing. Controls like this support mouse interactions, but cannot get keyboard focus.
TCustomControl: This a descendant of TWinControl. It also implements a Canvas and allows you to override the Paint method to draw any content. Because it descends from TWinControl, it actually has a handle and can gain keyboard focus and process keyboard messages.
An other good candidate is TPanel (or rather TCustomPanel). It inherits from TCustomControl, so it has the same graphical properties, but it also contains functionality to draw borders and align child controls. I doubt if you would need this, though.
Of course you can derive directly from TControl or TWinControl, but then you will have to take care of some of this stuff yourself.
Note that it is better to put the actual card game logic in a separate class and only create visual controls for drawing. If you do that, you can still choose whether you want to have separate controls for each card, or you can choose to draw your whole card game on a single control or even directly on the form. I doubt if Windows' card games like Free Cell and Solitaire have over 50 graphics controls.
Is it possible to create a custom component, not only by adding extra functionality like methods and events, but also design the custom component (so that color, font, ... shouldn't be set when adding that component).
I would like to use this to construct a custom TDBGrid which I reuse and can just add to a form properly designed.
Thanks in advance!
Everything you can do in the designer you can "code into your component". Generally you just redeclare the new default values for properties and set / initialize them in the overriden constructor. Ie to create custom panel with red color as default you'd do
type
TMyPanel = class(TPanel)
public
constructor Create(AOwner: TComponent); override;
published
property Color default clRed;
end;
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited;
Color := clRed;
end;
Component templates should serve the task.
After you're created and installed the component, drop it on the form, adjust every property you want to, go Component-Create Component Template, choose name and palette page. Starting this moment you can select and drop your customized variant on the form
Since the copied component is a simple text inside clipboard, you can also copy-paste your customized component to a text file and when you need this copy, just select this fragment and copy it as a simple text, Delphi form will accept this object when you paste it. You even can organize a little storage for your saved component after the "end." in the module or inside comments, both will be safely bypassed by the compiler.
What i am trying to accomplish is to create new touchkeyboard.
First i created buttons which i derive from speed buttons.
That done, now i need to create multiple buttons and layout them somewhere. This is were i get stuck.
I created a new component which i derive from TGraphicControl (this should be my new touchkeyboard), but i don't know how to add components to canvas. I actually don't know whether i'm supposed to add them to canvas or to some other component (eg. panel)!?!
Is my approach OK?
Thanks in advance.
If you're creating a custom visual control, you need to create the buttons and position them manually. For example:
TOnScreenKeyboard = class(TWinControl)
public
constructor Create(AOwner: TComponent);
end;
[...]
constructor TOnScreenKeyboard.Create(AOwner : TComponent)
var
TempButton : TSpeedButton;
begin
inherited;
TempButton := TSpeedButton.Create(self);
TempButton.Parent := self;
TempButton.Top := 10;
TempButton.Left := 15;
TempButton.Caption := 'A';
end;
You can put the button creation into a loop and position each one according to where it should be.
(I wrote this off the top of my head, and I don't write a lot of Pascal anymore, so there may be some minor mistakes! But it should get you started.)
Because of your wording and confusion between Panel, Canvas and custom controls in general, I assume you're a Delphi beginner. You need to learn about frames: embarcadero docwiki link on frames
Frames allow you to create re-usable portions of GUI. You use the IDE to "draw" the frame, you can then place that composite control (the frame) onto forms or other frames. It's a very powerful feature and it's conceptually very close to what other languages call "custom controls" (very close to what asp.net or WPF consider a custom control to be).
In the Delphi world, when you say "custom control", people would normally expect you to want to create an reusable control that's placed in a package and it's installed in the IDE. It's an fairly advanced subject. If that's what you want then I misunderstood the question, sorry.