Latest Posts
Touch Demo Park IV
Previously I posted Part I, Part II and Partk III of the Touch Demo.This is the final step of the touch demo where I will be adding the inertia processing and mouse support. Mouse support is easy but requires a minor refactoring of the touch message handler so the mouse can piggy back on it. For CodeRage I did add a touch keyboard but I will leave that as an exercise for the user.
And now you can download source code from CodeCentral for all four demos.
Inertia processing requires the Manipulations unit. Then the object that is to be manipulated, in this case TGlowSpot, should implement the _IManipulationsEvents interface which is a COM event sync. Here is how that class changed:
TGlowSpot = class(TInterfacedObject, _IManipulationEvents)
private
FInertia: IInertiaProcessor;
FManipulator: IManipulationProcessor;
FInertiaCookie, FManipulatorCookie: LongInt;
FCompleted: BOOL;
public
X, Y, Radius: Integer;
Alpha: Extended;
FadeIn: Boolean;
Color: TColor;
ID: Integer;
protected
procedure DoTouch(const APoint: TPoint; AID: Integer; ATouchMessage: TTouchMessage);
{ _IManipulationEvents }
function ManipulationStarted(X: Single; Y: Single): HRESULT; stdcall;
function ManipulationDelta(X: Single; Y: Single; translationDeltaX: Single;
translationDeltaY: Single; scaleDelta: Single; expansionDelta: Single;
rotationDelta: Single; cumulativeTranslationX: Single;
cumulativeTranslationY: Single; cumulativeScale: Single;
cumulativeExpansion: Single; cumulativeRotation: Single): HRESULT;
stdcall;
function ManipulationCompleted(X: Single; Y: Single;
cumulativeTranslationX: Single; cumulativeTranslationY: Single;
cumulativeScale: Single; cumulativeExpansion: Single;
cumulativeRotation: Single): HRESULT; stdcall;
public
constructor Create(AParent: TWinControl);
procedure Paint(Canvas: TDirect2DCanvas);
procedure Disconnect;
procedure ProcessInertia;
end;
...
Each TGlowSpot needs to hold on to an instance of the inertia processor and the manipulation processor and then connect up to them with the event sync. That is done in the constructor:
constructor TGlowSpot.Create(AParent: TWinControl);
begin
inherited Create;
Alpha := 1;
Radius := 80;
FadeIn := False;
Randomize;
Color := RGB(Random(255), Random(256), Random(256));
ID := -1;
FCompleted := True;
ID := -1;
FCompleted := True;
FInertia := CreateComObject(CLSID_IInertiaProcessor) as IInertiaProcessor;
FManipulator := CreateComObject(CLSID_IManipulationProcessor) as IManipulationProcessor;
InterfaceConnect(FInertia, _IManipulationEvents, Self, FInertiaCookie);
InterfaceConnect(FManipulator, _IManipulationEvents, Self, FManipulatorCookie);
FInertia.put_DesiredDeceleration(0.001);
FInertia.put_BoundaryLeft(200);
FInertia.put_BoundaryTop(200);
FInertia.put_BoundaryRight(AParent.Width - 200);
FInertia.put_BoundaryBottom(AParent.Height - 200);
FInertia.put_ElasticMarginLeft(200);
FInertia.put_ElasticMarginTop(200);
FInertia.put_ElasticMarginRight(200);
FInertia.put_ElasticMarginBottom(200);
end;
And then of the disconnect is done like this:
procedure TGlowSpot.Disconnect;
begin
InterfaceDisconnect(FInertia, _IManipulationEvents, FInertiaCookie);
InterfaceDisconnect(FManipulator, _IManipulationEvents, FManipulatorCookie);
end;
The inertia processing is handled with each WM_TOUCH message that is fired. It's pretty simple really, if there is a move, call the manipulation COM object's ProcessMove, and do the same with down. Up is a bit different because of the inertia but all you need to do is set the velocity and the location.
procedure TGlowSpot.DoTouch(const APoint: TPoint; AID: Integer;
ATouchMessage: TTouchMessage);
var
Vx, Vy: Single;
begin
case ATouchMessage of
tmMove:
begin
X := APoint.X;
Y := APoint.Y;
FManipulator.ProcessMove(AID, APoint.X, APoint.Y);
end;
tmDown:
begin
X := APoint.X;
Y := APoint.Y;
FManipulator.ProcessDown(AID, APoint.X, APoint.Y);
end;
tmUp:
begin
ID := -1;
FManipulator.ProcessUp(AID, APoint.X, APoint.Y);
FManipulator.GetVelocityX(Vx);
FManipulator.GetVelocityY(Vy);
FInertia.put_InitialVelocityX(Vx);
FInertia.put_InitialVelocityY(Vy);
FInertia.put_InitialOriginX(X);
FInertia.put_InitialOriginY(Y);
FCompleted := False;
end;
end;
end;
function TGlowSpot.ManipulationCompleted(X, Y, cumulativeTranslationX,
cumulativeTranslationY, cumulativeScale, cumulativeExpansion,
cumulativeRotation: Single): HRESULT;
begin
Result := S_OK;
end;
function TGlowSpot.ManipulationDelta(X, Y, translationDeltaX, translationDeltaY,
scaleDelta, expansionDelta, rotationDelta, cumulativeTranslationX,
cumulativeTranslationY, cumulativeScale, cumulativeExpansion,
cumulativeRotation: Single): HRESULT;
begin
Inc(Self.X, Round(translationDeltaX));
Inc(Self.Y, Round(translationDeltaY));
Result := S_OK;
end;
function TGlowSpot.ManipulationStarted(X, Y: Single): HRESULT;
begin
Result := S_OK;
end;
procedure TGlowSpot.ProcessInertia;
begin
if not FCompleted then
FInertia.Process(FCompleted);
end;
The last bit of code I want to talk about is the mouse handling. I refactored the handling of the WM_TOUCH message into WMTouch and ProcessTouchMessages. ProcessTouchMessages is the common function that the mouse message can call to get the same inertia behavior.
procedure TTouchForm.WMTouch(var Message: TMessage);
function TouchPointToPoint(const TouchPoint: TTouchInput): TPoint;
begin
Result := Point(TouchPoint.X div 100, TouchPoint.Y div 100);
PhysicalToLogicalPoint(Handle, Result);
end;
var
TouchInputs: array of TTouchInput;
TouchInput: TTouchInput;
Handled: Boolean;
Point: TPoint;
TouchMessage: TTouchMessage;
begin
Handled := False;
SetLength(TouchInputs, Message.WParam);
GetTouchInputInfo(Message.LParam, Message.WParam, @TouchInputs[0],
SizeOf(TTouchInput));
try
for TouchInput in TouchInputs do
begin
Point := TouchPointToPoint(TouchInput);
if (TouchInput.dwFlags and TOUCHEVENTF_MOVE) <> 0 then
TouchMessage := tmMove
else if (TouchInput.dwFlags and TOUCHEVENTF_UP) <> 0 then
TouchMessage := tmUp
else if (TouchInput.dwFlags and TOUCHEVENTF_DOWN) <> 0 then
TouchMessage := tmDown;
ProcessTouchMessages(Point, TouchInput.dwID, TouchMessage);
end;
Handled := True;
finally
if Handled then
CloseTouchInputHandle(Message.LParam)
else
inherited;
end;
end;
function TTouchForm.ProcessTouchMessages(const APoint: TPoint; ID: Integer;
TouchMessage: TTouchMessage): TGlowSpot;
var
Spot: TGlowSpot;
begin
Result := nil;
Spot := FindSpot(ID);
if Spot = nil then
begin
Spot := FindSpot(APoint);
if Spot <> nil then
Spot.ID := ID;
end;
if Spot = nil then
begin
Spot := TGlowSpot.Create(Self);
Spot.ID := ID;
FSpots.Add(Spot);
end;
Spot.DoTouch(APoint, ID, TouchMessage);
Result := Spot;
end;
And last the mouse handling functions with the check for ssTouch in the Shift parameter. If that check wasn't there each message would happen effectively twice because the touch messages also send mouse messages for backwards compatibility with applications that don't support touch.
procedure TTouchForm.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if ssTouch in Shift then Exit;
FMouseDown := True;
ProcessTouchMessages(Point(X, Y), 0, tmDown);
end;
procedure TTouchForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if ssTouch in Shift then Exit;
if FMouseDown then
ProcessTouchMessages(Point(X, Y), 0, tmMove);
end;
procedure TTouchForm.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
Spot: TGlowSpot;
begin
if ssTouch in Shift then Exit;
Spot := ProcessTouchMessages(Point(X, Y), 0, tmUp);
Spot.ID := -1;
FMouseDown := False;
end;
I just realized that there is a bug in the program. It will run just fine but crash pretty bad if it runs too long. I guess I never demoed it very long before. So I'll leave debugging this crash as an exercise for the user.
posted @ Thu, 19 Nov 2009 13:00:00 +0000 by Chris Bensen
Tech Republic: A developer’s hands-on review of Delphi 2010
Justin James, in his Tech Republic Programming and Development blog, has posted a review of the new Delphi 2010. The sub-text for the online review article says, "According to Justin James, .NET and Visual C++ developers should check out Embarcadero’s Delphi 2010…". Our Embarcadero Delphi is one of the most respected and widely used Rapid Application Development (RAD) environments. Over 1.7 million developers worldwide choose Delphi over other tools because Delphi radically speeds desktop, workstation, touch, kiosk, and Web application development without sacrificing an ounce of programming power or control. Applications built with Delphi are lightning fast, compact, provide rich UIs, and can connect with virtually any database or data source “out-of-the-box”.
A few other tidbits from the review:
- "the good folks at Embarcadero came up with a brilliant idea called IDE Insight"
- "Another item that I really like is DataSnap, which is similar to WCF in concept, but in execution, it feels much smoother."
- "Delphi 2010 supports all sorts of new goodies, including multi-touch and gestures … beating Visual Studio 2010 to market by nearly six months"
- "Delphi 2010 has good tools for debugging multithreaded applications, which is an increasingly important item"
- "If you want to do Windows development, and you want to work with native code in a native style, I think that Delphi 2010 is a very productive tool."
Finally, in the summary, Justin gives the Delphi team the ultimate developer compliment, "Every time I work with the Embarcadero team, I feel like they are writing the tools that they would love to use; they really are developers’ developers, and they understand the development process very well and implement it as tools quite nicely."
Read the complete review at http://blogs.techrepublic.com.com/programming-and-development/?p=1924
Share This | Email this page to a friend
posted @ Thu, 19 Nov 2009 12:15:24 +0000 by David Intersimone
Oracle's Cardinality Hint, Profiles, Outlines and SQL Baselines
Interesting question. I had an online dialog with a guy name Randolf Geist a year ago or so where he convinced me to look closer at SQL Profiles. Up until that point I had only seen SQL Profiles that were created by the SQL Tuning Advisor and I was not very impressed. They tended to go sour after a little time because of the OPT_ESTIMATE hint, but I digress. The answer is yes, I think SQL Profiles have a couple of advantages over Outlines at this point.
1. They have the ability to be used on multiple statements (ones that are the same except for literals) using the force matching signature bit.
2. They are newer. I’m starting to worry about Outlines getting buggy due to lack of attention. Documentation says they are deprecated and although they continue to work in 11g, I am a bit leery of continuing to use them at this point. (the whole hint based mechanism is tricky enough as it is).
11gR2 includes a procedure to migrate Outlines to Baselines by the way (DBMS_SPM.MIGRATE_STORED_OUTLINE). At any rate, I am not implementing Outlines at this point.
posted @ Wed, 18 Nov 2009 16:30:00 +0000 by Kyle Hailey
Simplify ER/Studio Licensing & Provisioning with Embarcadero ToolCloud™
Simplify ER/Studio Licensing & Provisioning with Embarcadero ToolCloud™ Most ER/Studio users do more than just physical database design or data architecture. We’re data architects, business analysts, DBAs and developers, using a wide array of different tools from different vendors to support our application and database projects. Just managing the licensing and provisioning of these tools can [...]
posted @ Wed, 18 Nov 2009 08:18:32 +0000 by Josh Howard
Migration Webinar follow-up…
All,
Thanks for putting up with my voice yesterday. I hope some of the information was worth the time! As I stated yesterday, the Parser.exe created by Ander’s is available on his blog: http://blogs.embarcadero.com/ao/ and the actual Code Central location is: http://cc.embarcadero.com/item/27398
I was also thinking about doing a part II to the session, where we go through the entire Sanctuary program that we only hit on for about 5 minutes (no slides, just code). I think there are a few things that I could show that may help other people. Let me know your thoughts of if you think it would be worth it.
Again, thanks all for coming!
Mike
More to come…
Share This | Email this page to a friend
posted @ Wed, 18 Nov 2009 15:02:19 +0000 by Michael Rozlog
DBArtisan now supports Microsoft SQL Azure databases
Today, at the Microsoft Professional Developers Conference (PDC’09) in Los Angeles, Embarcadero Technologies announced DBArtisan for the SQL Azure database from Microsoft. The special edition of DBArtisan helps organizations expedite the deployment and simplify the management of cloud-based databases and applications.
DBArtisan for SQL Azure provides for basic database administration at the schema level, including object management and editors, SQL editing and schema extraction, as well as migration utilities to facilitate data migration from Microsoft SQL Server to SQL Azure. The tool enables enterprises to build symmetrical on-premise and cloud-based SQL Azure Database deployments, reducing in-house IT infrastructure costs and making certain data sets more readily available to offsite consumers.
Developers and database administrators can download a trial version of DBArtisan for SQL Azure. Information about the steps to download and register the trial are listed on the DBArtisan for SQL Azure product page. You’ll also need a Microsoft SQL Azure account.
- DBArtisan for SQL Azure product page
- Read the press release
- Watch the demonstration video
- Download the trial version
- DBArtisan product page
Share This | Email this page to a friend
posted @ Wed, 18 Nov 2009 12:18:57 +0000 by David Intersimone
Explain Plan vs Real Plan on Oracle
A good part of my presentation Friday at NoCOUG was on explain plan command being an estimate of the actual execution plan. Now on the Oracle-L forum list, I see the same question being asked "Under what conditions, could the plan I get out of ‘explain plan’ differ from what I get from running the sql statement?" and Tanel Poder giving a succinct clear list of reasons:1) The optimizer statistics the EXPLAIN PLAN ends up using are different from the statistics the other session ended up using
2) Explain plan does not use bind variable peeking thus will not optimize for current bind variable values
3) Explain plan treats all bind variables as VARCHAR2, thus you ma have implicit datatype conversion happening during the plan execution, (meaning to_char,to_number functions are added around variables/columns) and this for example may make optimizer to ignore some indexes if you get unlucky.
posted @ Tue, 17 Nov 2009 08:46:00 +0000 by Kyle Hailey
Future of Cloud Computing and Relational Databases
I was talking to someone from Amazon who indicated that Amazon is moving more and more processing away from Oracle into the middle tier and object oriented databases with the idea being to reduce usage of Oracle and to improve processing time. The time it takes me as a consumer to put an order in can be reduced if Amazon just at takes all my information and says "purchase complete" and then process all the data and mails me later if anything goes wrong.posted @ Mon, 16 Nov 2009 10:52:00 +0000 by Kyle Hailey
Clean Installs (Embarcadero's All Access)
posted @ Sat, 14 Nov 2009 16:33:00 +0000 by Kyle Hailey
Oracle Users Group - NoCOUG Fri 13th
Tanel Poder's Blog
posted @ Sat, 14 Nov 2009 14:58:00 +0000 by Kyle Hailey


