In Delphi, I have two edit boxes and a button.
Edit1 is selected by default. I want to change focus using messages. But if I do as below, it all gets messed up with selection ranges in both edits, caret in the wrong box etc.
The reason I'm using messages is so that I can control focus in an external application. This seems to work, up to a point but clearly, the windows internal state is a bit scrambled. I don't have the source for the external program.
procedure TForm1.Button1Click(Sender: TObject);
begin
PostMessage(edit1.handle,WM_KILLFOCUS,0,0);
PostMessage(edit2.handle,WM_SETFOCUS,0,0);
end;
... So can it be done? Am I missing a message?
WM_SETFOCUS and WM_KILLFOCUS are both notification messages that Windows sends to window handles when they receive and lose input focus, respectively, and you should not post those yourself. Instead, simply call SetFocus(edit2.handle) or edit2.SetFocus() to set the focus.
If for some reason you can't do that synchronously from your button click handler, you can post a custom message to a local message handler in your own form and make the SetFocus call from that message handler.
Related
Using this tutorial and translating on the fly to VS2019 IDE. Got to step of "Adding Message Handlers for the Controls" and trying to locate BNCLICKED in Class Wizard Messages tab. I see many other WM_XXXBUTTON... messages but no BNCLICKED. What replaces BNCLICKED?
The WM_XXXBUTTON... message you refer to (such as WM_LBUTTONDOWN) are messages sent when a mouse button does something. For buttons in dialog boxes (and other UI components), the 'message' sent is BN_CLICKED (note the underscore). Technically, this is a notification code rather than a message in its own right, and is sent as the high word of the wParam of a WM_COMMAND message.
Right now I'm struggling to solve a bug that caused by the dataset mode at Delphi (using ADODataset),
details as below for the add button mechanism :
IDMain: =self.DBTextIDUser.Caption+'-'+self.DBEditWorkingDate.Text;
datamodule1.ADODataSetWorkingDetails.Append;
with datamodule1.ADODataSetWorkingDetails do
begin
dbgridworkinghours.Fields[0].AsString := IDMain;
dbgridworkinghours.Fields[7].AsString := self.DBTextIDUser.Caption;
dbgridworkinghours.Fields[8].AsString := self.DBTextName.Caption;
dbgridworkinghours.Fields[9].AsString := self.DBEditWorkingDate.Text;
dbgridworkinghours.Fields[11].AsString := self.DBTextPeriod.caption;
dbgridworkinghours.Fields[10].AsString := self.DBTextToday.Caption;
end;
I already set the adodataset to append mode at the save button :
datamodule1.ADODataSetWorkingDetails.post;
when I click the save button, an error appears that:
The adodataset not in edit/insert mode
I already used this mechanism at the other form and it works
note: I already tried setting the adodataset mode to insert, but still faced the same error
What #kobik said.
Your problem is most likely being caused by something you haven't told us in your q.
I think the important thing is for you to find out how to debug this sort of thing
yourself, so that even if you don't understand the cause, you can at least isolate
it and provide better information when you ask for help here. So I'm going to
outline how to do that.
In your Project Options, check the box "Use Debug DCUs"
Set up two event handlers, for your ADODataSetWorkingDetails's
AfterPost and AfterScroll events, put a some "do nothing" code in both of them
(to stop the IDE removing them). Put a debugger breakpoint on the first line
inside the AfterScroll handler, but not (yet) the AfterScroll one.
Compile and run your program.
You should find that somewhere after you call Append but before you click your
Save button, the debugger stops on your AfterPost breakpoint.
When it does,
go to View | Debug windows | Call stack. This will show you a list of
program lines, the one at the top being the one closest to where the breakpoint
tripped. This will likely be deep inside the VCL's run-time code (which is why
I said to check "Use Debug DCUs". Scroll down the list towards the bottom, and
eventually you should come to a line which is the cause of why Post was called.
If it isn't obvious to you why the AfterPost event was called, put a breakpoint
on your Append line and run the program again. When this breakpoint trips,
put another breakpoint inside your AfterScroll event, resume the program
by pressing F9 and see if the AfterScroll breakpoint is hit. If
it is, again view the Call stack and that should show you why it was called -
if it isn't obvious, then add the contents of tthe Call stack window to your q.
If the cause is obvious, then change your code to avoid it.
The reason I've gone on about the AfterScroll event is that what isn't obvious
is that when your code causes a dataset to scroll, any pending change (because
the dtaset is in dsInsert or dsEdit state will cause the change to be posted
and you will then got the error you've quoted if you try to call Post on the
dataset again. Calling Append initially sets a dataset into dsInsert state, btw.
See if you can at least identify what is causing your dataset to post before
it is supposed to, and let us know in a comment to your q or this answer.
Btw, I strongly recommend that you get out of the habit of using the with construct in your code. Although it may save you a bit of typing, in the long term it will likely make bugs far more likely to happen and far harder to find.
Update TDataSet and its descendants have a State property which is of type TDataSetState (see
DB.Pas). Normally, for browsing data and navigating around the dataset, the
dataset is in dsBrowse state. If you call Edit or Append (or Insert), the dataset
is temporarily put in dsEdit or dsInsert state, respectively. Various routines in DB.Pas
check the dataset state before certain operations are performed and raise an exception if the
DataSet in not in the correct state for the operation to go ahead. It is very, very likely
that it is one of these checks that is giving you the exception.
My original hunch was that your error was occurring because something was happening which
was causing Post to be called, because if Post succeeds, it puts the dataset back into
dsBrowse state, so when clicking your Save button calls Post, the dataset is already
in dsBrowse state. You can, of course, put a breakpoint in TDataSet.Post in DB.Pas
check which state the dataset is actually in when it is called.
There are two other main possibilities for the cause of your exception, namely that
either TDataSet.Cancel or the general Abort method is being called. To investigate
these, put breakpoints on the first lines inside TDataSet.Cancel (in DB.Pas) and
Abort (in SysUtils.Pas). If either of these breakpoints trips between you calling
Append and Post, then you can use the Call Stack view to try and figure
out why execution has reached there.
I was wondering how i could make a callback function for the twebbrowser in delphi. I want it to recognize which input or edit box i am clicking in with the mouse..... any ideas?
As requested, hereby the update of the question, the user workflow.
The user would
1. select the inputfield on the twebbrowser by mouse. (the program would see what the information is about this inputfield(value, id, etc.....)
2. fill in the field with prefered information (name, password, whatever really)
At the same time this text is linked back into a memo box. That whould be the start, if i understand this it would be a good beginnning.
Will this code help you?
http://www.delphidabbler.com/articles?article=22&part=4#calling-delphi
The article is about calling Delphi-code from JavaScript.
I have an application with two forms, both are dialogs and they both have memo boxes in them and they both have an OK button on them, however one dialog behaves differently from the other - if I am in the memo area and i type something and then press enter, the form closes but in the other form it goes to the next line in the memo (this is how I want it to behave).
I don't know how to fix the other form so that pressing enter inside the memo does not close it but makes it go to the next line. I even copied the memo component from the 'good' to the 'bad' form and it still does that, also compared the form properties but they are the same! Any idea why this is happening?
Two possibilities:
1) The Memo needs to have the WantReturn in order for the memo itself to process the RETURN key.
2) Check any KeyPress/KeyDown/KeyUp handler on the form that doesn't work to see if they process a RETURN key. If the form has KeyPreview=TRUE then the form's keyboard handler will be executed BEFORE the memo's and if the form's keyhandler processes RETURN then the memo will never see it.
I'm developing a Word addin in Delphi, on a task pane I put a Virtual treeview, in the OnFocus event of the Virtual Treeview I call Word to insert a file into the current Word document via method ActiveDocument.Range.InsertFile, but this operation will put the input focus back to the Word document window, so finally in this event handler I call TreeView.SetFocus to set the focus back to the treeview, this works except that the Word document window still has a unblinking caret shown.
I tried sending the WM_KILLFOCUS windows message to the handle of the Word document window but no luck. Any hints? Thank you in advance!
You can try to call Application.BringToFront or Application.MainForm.BringToFront.