IDropSourceNotify - how to implement - delphi

I want to implement a OLE Drag&Drop feature. Doing this, I have to detect the mouse button is clicked and moved. Than I call DoDragDrop to start the Drag&Drop feature.
To receive the Drag&Drop feature, I have to call RegisterDragDrop before of it to register a window as a target of the Drag&Drop operation. Like the most applications, my main window based on several sub windows: TreeView, ListView, Edit, etc.. With IDropTarget::DragOver I can detect, if the target sub window accepts the Drag&Drop operation. This works fine, if I drag an object from a different application and the mouse cursor shows as well, if the target sub window accept the Drag&Drop operation.
But if I start the Drag&Drop feature inside my application with DoDragDrop the mouse cursor does now change automatically. Why?
So I can use the IDropSource::GiveFeedback method to change the cursor of the target sub window. But I can't find out, which sub window has to change the cursor.
If I'm right, the IDropSourceNotify should provide this informations. But how can I involve this class into the Drag&Drop operation?
Additional, I don't understand, why I have to handle the mouse cursor by my self, if the source window is inside my application - but it will be handled automatically, if the source window is inside an other application.
Last but not least, if I change the cursor of my sub window inside IDropSource::GiveFeedback it will be shown like I changed it. But since the my main thread is inside DoDragDrop I wonder how Windows detect the changed cursor. If I'm right, Windows ask my application with the WM_NCHITTEST message, which cursor should be shown. But how does my application answer this message, while the main thread is blocked inside DoDragDrop?
I'm working with Delphi XE4 on a Window 7 system.

The drop source should not make any assumptions about the drop target - and should never attempt to modify the UI of the target.
In other words: Do not mess with the cursor property of the control under the cursor.
The return value from IDropSource.GiveFeedback instructs Windows to either use the standard drag drop cursors or let you handle that detail yourself.
If you return DRAGDROP_S_USEDEFAULTCURSORS then the standard cursor corresponding to the current drop effect (the parameter passed to GiveFeedback) will be used. If you return S_OK then you can set the cursor by calling the SetCursor API function.
I would recommend that you just return DRAGDROP_S_USEDEFAULTCURSORS.
Actually unless you have a burning desire to learn the inner details of COM based drag and drop I would recommend you Google "drag drop delphi" and use one of the already available libraries.

Related

Delphi TTaskDialog show/hide or start/stop marquee progress bar

I have a TTaskDialog that has an OnButtonClicked event handler, in which a lengthy process (several seconds) is performed. This works fine, but I'd like some indication to the user that things are happening while that lengthy process is chugging along. I would like to have a marquee progress bar on the dialog that is initially hidden, appears when the CommandLink is clicked, and runs while the lengthy process is performed - I'd settle for a progress bar that is visible but not enabled when the dialog is displayed and is "turned on" in the OnButtonClicked event. Just including the tfShowMarqueeProgressBar flag causes the bar to appear and be scrolling when the dialog first displays, and the ProgressBar property of the dialog doesn't have Enabled or Visible type properties to control this behavior.
There are TaskDialogs in Windows itself that do what I want, so I know it's theoretically possible, though I realize that the structure of the VCL wrapper around the native control may make it difficult or impossible using the VCL object.
Is what I want possible using the TTaskDialog VCL object?
The Windows API provides the message TDM_NAVIGATE_PAGE to change the TaskDialog at runtime. You would have to pass a TASKDIALOGCONFIG structure along with this message that defines the dialog's properties. In its dwFlags field you could specify the TDF_SHOW_PROGRESS_BAR flag to show the progress bar. But this requires a lot of work as the other fields in the TASKDIALOGCONFIG structure must match the properties that you have set for Delphi's TTaskDialog component.
Delphi creates a TASKDIALOGCONFIG structure as a local variable in the function TCustomTaskDialog.DoExecute in Dialogs.pas that is used to display the TaskDialog.

How to restore/clear form position after multi-monitor setup change

Within the IDE, when F12 toggles between code and form,
the forms are displayed outside the monitor borders,
and therefore not visible.
This happens after a multi monitor setup has changed,
and the forms no longer open within the available new monitor screen areas.
One way to resolve this is to use the property inspector and
set the Top/Left properties to 4 to make the forms visible.
This is however a lot of work,
especially if many forms and possibly many projects are involved.
Is there a better way to reset the form locations once and for all,
so they are all visible with the new monitor setup?
There is nothing (AFAIK) in Delphi 6 IDE that would help. But assuming you are using Windows, the help is near, (tested on Windows 7):
Right-click on taskbar and select 'Cascade windows', this affects all windows in one go.
or
Alt-Tab to the window, press Alt-Space and then M (for move). Move the window with the arrow keys. This you would have to do seperately for each window.
Close your Delphi IDE. Then, if your current project group file is xyz.groupproj, open the file xyz.dsk with an text editor. Look for section [UndockedDesigner] entry "Count" and change its value to zero.
[UndockedDesigner]
Count=0
That will force all design window positions to 0,0 on your main monitor.

Delphi - Activating the Hint from another control of Application

I'm trying to activate Hint from control of different application created from delphi upon focus, I'm using hook to identify the focused control, and then use WM_MOUSEMOVE, which I think will activate the Hint of that control, the handle would be the Control itself and the lParam is the Left and Top of the Control. The Control activate the OnMouseMove Event, but the Hint never shows. but when I use SetCursorPos, Hint show, but I need to show the Hint with out the cursor move on that Control. Can you please help me with this? Thank you in advance... by the way I'm using Delphi XE4
Among the really asked question is how to show the hint of a control that resides on another application (i am afraid without hook that application can not be done), the title is "Delphi - Activating the Hint from another control of Application".
First is first: That can be done without knowing what language the other app was done, but it is very complex to put it here (and i am not an expert on such way of coding, also i hate apps that work that way).
Second: The main idea is to hook the other application, search on Google some code of that apps, that can show you a rectangular hole square of the object the mouse is passing over, that application while doing it is iconized (i do not remember the name of it).
Waht such app does: As you move the mouse over the screen it overlays a rectangular over the control that mouse is over, then if you press the key to print screen, that small region is the only thing that goes to clipboard; on of such apps i saw had an extra funcion, they can move such controls if you press cursors on keyboard, also can hide/enable/disable such control... more, it can also make controls that are invisible to be visible, etc... i saw it working on my computer, and hey, for fun it is pretty and to DeBug or get extra things on some apps is also great (make some menĂºs to be visible and enabled and then can use such funtions).
Please, please, understand i am agaist piracy and also against using such apps to let code to be run... some apps need pay for letting some menus enabled, but they have the code there, no need to change EXE to have/use that menus; just using this kind of apps makes that limited apps to be unlimited (just enable or show hidden menus and voila).
Note: To unhide menus, mouse point is not needed to be over the app, can be anywhere and is not moved.
The idea i want to say is: Any app can move, alter any control on any other app (at least on Windows) that is running, so maybe there can be a way to show such hint.
In the past i had use such app (sorry i do not remember the name) for DeBug my own apps, so i do not need to recompile in such cases where something was wrongly hidden, also work with buttons, labels, texts, combos, memos, etc.
Now my small problem is: I just need exactly what title say, but i can not make it to work.
Must be:
Mouse position must be irrelevant (it also must be able to be outside the application)
Just when a button that has focus is pressed with keyboard (Space or Enter) or just after some code somewhere on my application, i want to show the Hint of a specific TEdit for a short period of time.
I did not get Hint to be shown; not unless mouse point is over such TEdit but i want/need mouse pointer to not be over it, neither it to jump to the TEdit.
Idea Conept for that Hint to be shown: After doing some code that changes something, show extra info associated.
Example:
A button with that loads a file using an open dialog, filename is put on a ReadOnly TEdit (so it let user copy the text, but not change it); i want extra info that i punt on .Hint of such TEdit to be shown inmediatly.
That hint use is for not overload window with a lot of fields (TLabels) for showing such file data.
Simple idea: such Hint shows TimeStamp and size of the selected file.
P.D.: Not much related (since i am trying with a normal plain text hint), but hints can also store a full HTML page and with 3rd party tools be shown as an HTMLhint, so they can show a lot info of that file (also its content, etc) in a web based format; as i say i first try with standard plain text hints.
In order to show hint programatically you need to call TApplications ActivateHint method to which you specify the position parameter.
http://docwiki.embarcadero.com/Libraries/XE3/en/Vcl.Forms.TApplication.ActivateHint
Based on position parameter Application automatically finds which controll is at that position and shows its hint.
NOTE: Position parameter screen coordinates in pixels and not your controll coordinates. So you will have to use ClientToScreen method to change your coordinates apropriately.
You can see simple example of how to use this here: https://stackoverflow.com/a/15031208/3636228
Now if you need to do this from another application then you will have to add some comunication mechanizm to these two application so that one could send a proper message to tell the other to show the hint at specific position. But this does require you to be able to change both applications.
EDIT: This works with VCL applications but I'm not sure if it would work with FireMonkey applications.

Using barcode scanner with Delphi

I'm developing a POS (pet project) and I'm thinking of adding a bar code scanner to capture the sales faster. I do not have a scanner at the moment with me, and would like to ask some questions, as I'm stuck a bit.
On the sales screen my initial idea was to have an TEdit component and when a person scans the product it would fill the TEdit with the string. Now the problem I'm encountering is that I want to make the TEdit invisible so that the person does not see it. But once you make the TEdit invisible, you cannot set focus on it, so that plan cannot work.
So can anyone suggest what I can use to "capture" the scanned string? How would I make the component to listen and wait for the scanner? I assume that the scanner would be like a normal keyboard event, like button down or up.
There's KeyPreview property on TForm. Set it to true, so all key presses are processed by form first before controls.
Article about keyboard processing in Delphi: http://delphi.about.com/od/objectpascalide/a/keyboard_events.htm
Related SO question: How does Delphi's KeyPreview work?
What I have done is use the KeyPreview to monitor for a function key like F9 which the bar code scanner is set to prefix scans with. When this is received, I pop up a dialog with a single edit box and OK button. This then receives the rest of the barcode information, and the scanner ends the entry with the Enter key. I can then determine the purpose of the scanned data (in my case, one type starts with a prefix) and then put the data into the appropriate field on my main form.
I chose F9 because it seems inert in most applications, so you can use the scanner in other ways, but I support other keys too for flexibility. My application also has a scanner test mode where it shows the keys sent.
You can use a TEdit with a height and width of 0 so it won't appears and make sure it get focused when you scan your barcode.
You can also place the TEdit outside of the visible window, setting the component's Top and Left properties to something like -50. You can then set focus to it just like a regular visible TEdit box, but it will be invisible to the user.

Detecting is something being dragged over my application

I need to know is some object being dragged over my Delphi application.
For example: while the user dragging some item from ListView to ListBox, or dragging some file from Explorer into my LitsView, I want to check at any moment is he still dragging or not dragging anymore.
Can I find this without hooking drag events?
Delphi XE
I would do this by making a note when the drag process starts, for example when IDropTarget.DragEnter is called. And then reset the flag when the DragLeave or Drop is subsequently called.

Resources