Okay, I have an on-screen keypad made up of a panel with buttons with the kind of functionality you would expect 0 .. 9, Delete, BkSpace and Enter. It's an application for a touchscreen system.
The values entered by "pressing" the keys are shown in a TEdit. Almost all of it works perfectly, but I have an issue with passing a keystroke to the TEdit control when I want to backspace within the TEdit. I can simply delete the last character in the TEdit by using the Copy function and I guess I could do something similar for Delete.
But it would be much neater to pass the "key" button tag for backspace to the TEdit control and have it convert that to VK_BACKSPACE or VK_DELETE.
The problem is that while I've captured and used the virtual keycodes before, I've never tried to pass one to a control's event before and I can't find anything which really helps, either here or doing a general search or trawling through the Embarcadero documentation.
I'm sure this is dreadfully simple and I'm missing something easy, but could somebody point me at it, please?
I think you are looking for the SendMessage() method. Here is an example:
http://www.swissdelphicenter.ch/de/showcode.php?id=220
Related
I apologize in advance for this vague question but can anyone give me a pointer to this problem?
The Delete key does not work as normal in my application. e.g. The Delete key has no effect in an editbox (i.e. it will not delete highlighted text) but Shift Delete does work. This seems to be the case thoughout the application. I have disabled all keypreviews and OnKey events in case they were causing it but the problem persists.
Can anyone suggest where I might look for the problem?
Running Windows 10 Delphi 10.3.3
If this happens only in this particular application, it is likely that you have a TActionList or TActionManager with an action using Delete as its shortcut, or a simple menu item with such a shortcut.
For instance, you might have an Edit menu with a Clear item using Delete as its shortcut:
Then that action or menu item will respond to Delete, not allowing the focused control to do its own thing.
This kind of mistake is surprisingly common. For instance, in the Delphi IDE, you have an edit field above the editor, showing you the current class:
If you select this text and press Ctrl+C, you expect it to end up in the clipboard. But no! Instead, the selected text in the code editor (if any) is copied, even though the code editor didn't have keyboard focus.
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.
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.
I like the idea of the Delphi Code Insight window (custom listbox on form without borders basically) where you can click outside of the form and it will close it automatically.
My first thought was to call SetCapture/ReleaseCapture in the FormCreate and FormDestroy respectively. I set the form's caption to X/Y on the FormMouseMove, but it doesn't update the coordinates outside of the form.
If I call SetCapture/ReleaseCapture from within MouseDown and MouseUp, it does update the coordinates as expected, so that proves the concept does work.
I tried other things as well, e.g. post a WM_USER in the OnShow event, and call SetCapture from there, but it still doesn't update the coordinates. I then tried the TApplicationEvents component (OnMessage), but that doesn't work either.
I've read several articles already, but wasn't able to find what I was looking for. Some articles called SetCapture from within the MouseMove, but that doesn't work when the mouse cursor starts outside of the form. Hrm...
The next step would be to use a WindowsHook, but that's where I stopped. I know how to implement one, but it just seems like I'm missing something really obvious here. There must be a simpler way to do this.
Any ideas? :)
Cheers,
Jarno
What you want can be done easier by adding TApplicationEvents to your form and use the event OnDeactivate. That one gets triggered whenever the application loses focus.
Maybe WM_NCHITTEST can help you somehow. As they say, if the mouse is captured, this message is sent to the window that has captured the mouse. So I would capture the mouse for the form and then wait until result of this message is HTNOWHERE, which should mean "out of the window".
But as far as I can remember, this never worked for me fine, so I finally used (as you mentioned) mouse hook.But in my case I've had a lot of components on that popup form and you need to consider messaging for them too.
The implementation I've used (with a little changes) and which works is here.
I had a similar problem (I needed to implement a scrolling windows if the mouse pointer hovered over a special area and I was not able to use SetCapture)
and circumvented it using a timer + GetCursorPos method.
Just do then a ScreenToClient and check if the mouse is within the window.
Question:
Can anyone point to an article or code samples anywhere on how to
provide BOTH editing AND range selection in a TStringGrid?
Yes, I KNOW there are third-party grids that do this, but it's
frustrating that the built-in grid lacks this basic capability.
Background:
It's pretty normal to expect to be able to both edit a cell in a grid,
and also to select a range of cells such as for a Copy operation.
As delivered, TStringGrid doesn't do that. It's either/or. In fact, the
docs tell us about the grid Options, "When goEditing is included in
Options, goRangeSelect has no effect".
However, it looks like it may be possible to do editing and rangeselects
in a TStringGrid anyway!!! Through careful use of the mousedown,
mouseup, selectcell and exit events, you can get dang close by switching
editing elements on and off at the right times. But I still don't have
it perfect, and that only covers mouse use, not keyboard changes.
I have not used the TStringGrid for this, so I can't provide a specific answer. But am I right in assuming you can manually (in code) start a cell being edited? That link implies it is possible even if the grid doesn't have goEditing included in its Options. (See below to work around this if this is not true.)
If so, I'd suggest the following approach:
Combined selection and edit behaviour
I find this is a good, Windows-standard-behaviour sort of approach:
Leave the grid in selection mode, so mouse and keyboard interaction selects cells
Trigger a cell being edited yourself, based on certain criteria (I think you are on the way to doing this from what you said in your last paragraph.) There are common ways to trigger editing, and the following criteria are what my programs follow when they do something similar with other controls:
Selection is normal. Ie, click to select, click and drag to multi-select, use the keyboard arrows and Shift or Control to select, etc.
A cell enters edit mode when either:
A cell is selected and the user presses Enter or F2 (F2 is the standard "Rename" or "Edit" shortcut, which works in a number of programs)
The user "slow-double-clicks" on a cell - ie, slow-double-clicks to select and edit, or clicks again, after a pause, on an already-selected cell. This mimics Explorer's behaviour, where if a file is selected and you later click on it, it enters the inline edit/rename mode. To implement this, record when a cell was last clicked (and selected.) If it is clicked again, and if the time is greater than GetDoubleClickTime then they have clicked twice, slowly, and enter edit mode. This allows you to distinguish between the first click to select, a double-click (to perform some kind of action), and a slow second click, to enter edit mode.
I also tend to check the mouse position, so that if an object is slow-double-clicked and it wasn't first selected (ie, this both selects the object and then enters edit mode) I verify the mouse hasn't moved very much. I use GetSystemMetrics to find the double-click distance, and check that the slow double click was within this box. (Because it's not a true doubleclick, I actually check the distance times 2. My action code is:
const int iMAX_MOVE_AMOUNT = ::GetSystemMetrics(SM_CYDOUBLECLK) * 2; (sorry, C++ not Delphi, but should be convertable easily enough!)
but I'm actually not certain if this is completely and utterly 100% to Windows guidelines. In practice users find it works as they expect, though.)
That should let you change between selecting and editing at the appropriate times with both the keyboard and the mouse.
Miscellaneous thoughts
You may find some of this is cleaner and easier to implement by subclassing TStringGrid and creating a new component. That will allow you to implement this in normal code and override the inbuilt behaviour (rather than event handlers) while keeping it invisible to the form code. It will also give you lower-level access to the mouse events or Windows messages than are exposed simply through events such as OnMouseDown. Finally, if there are problems with showing the editor when goEditing is included in Options, this will allow you to change that behaviour. You could also add your own events if you want your code to respond to certain things happening, such as creating an OnBeginEdit event, say.
Creating your own components is normally regarded as an advanced Delphi topic, but it's actually remarkably easy once you know how! This site has a few good topics that will introduce you to the subject in general, and if you go this route and encounter problems, Stack Overflow is of course a good place to ask questions :) The Embarcadero Delphi » VCL » Writing Components newsgroup / forum is also an excellent resource, in fact possibly even better than SO for this specific topic.
Hope that helps!
Yes it's old post, but the problem still exist on Delphi XE3.
To manage this feature I used next "trick" in SelectCell procedure :
if (ARow = StringGridParam.Row) then
begin
StringGridParam.Options:= StringGridParam.Options + [goEditing] - [goRowSelect];
end else begin
StringGridParam.Options:= StringGridParam.Options + [goRowSelect] - [goEditing];
end;