How PowerBuilder application act as host for another guest executable? - process

How i can run a 3rd party executable as child process in my PowerBuilder app?
The only objective i want to achieve is that the 3rd party exe file open and close just like we open and close a Sheet in PowerBuilder.
I dont want to give any other option to users of my app to close the 3rd party exe without closing my main PowerBuilder app. same way user is not allowed to run the 3rd party exe without running PowerBuilder app.
All that sound like some ActiveX behavior. So i can say if the 3rd party exe becomes an ActiveX then my objective is achieved. It is just my guess. really i can go for any other options that meets requirements.

If you have the window handle for the other app, you might be able to use the SetParent API function to attach it to a blank sheet window in the PowerBuilder app. The resize event of the sheet window would have to use the PB function Send to forward a resize event. The close event of the sheet window would then send the WM_CLOSE event.

There is a way you can open 3rd party exe like a response window within your PowerBuilder application. Though I am not sure if that will be useful to you as you want to open it like a sheet window. Anyway, the following is the code.
Local External Function Declration:
Function long FindWindowA (long classname, string windowname) LIBRARY "user32.dll" alias for "FindWindowA;Ansi"
Function Boolean BringWindowToTop (long classname) LIBRARY "user32.dll" alias for "BringWindowToTop;Ansi"
Local Function:
public function integer of_manage_third_party_exe ()
public function integer of_manage_third_party_exe ();///////////////////////////////////////////////////////////////////////////////////
//
// Returns 1 - window is not opened
// -1 : A window is opened so bring it to top
//
///////////////////////////////////////////////////////////////////////////////////
long ll_handle //unique id of window opened
ll_handle = FindWindowA(0,"Title of third party exe")
//If the window is not opened Then bring the window to top
If ll_handle > 0 Then
Post BringWindowToTop(ll_handle)
Return -1
End If
Return 1
Script in Activate event of your frame window/the window from which you are going to open the 3rd party exe:
of_manage_third_party_exe()
Script in CloseQuery event:
//if third party exe is open then don't allow to close the window
If of_manage_third_party_exe ( ) < 0 Then
Return 1
End If
I guess it will help you figure out rest of the places where you might have to use the of_manage_third_party_exe function based on your functionality.

Related

Access WebView2 newly opened window

If I run window.open("url") it will open url in new popup window, even if it is Edge WebView2. It will just have default Windows title-bar, and read-only url bar. I need to open url from WebView exactly in new popup window, via window.open("url").
Is there any way to access that window from my program as far as original WebView2 child-window? By accessing I mean injecting scripts, and getting js-response after injecting.
Or, at least, perhaps there is way to open url with some pre-injected script, like window.open("http://google.com -javascript: alert(5)")?
Update
Found MSDN article, probably this is what do I need. Trying to understand that.
Yes, the ICoreWebView2::add_NewWindowRequested event lets you intercept WebView2 opening new windows.
If you do nothing in the event handler, or don't subscribe to the event, you'll get a new popup like you describe. In script the return value of window.open is connected up to the newly opened popup window. But in your native code you have no access to or control over the newly opened window.
Or you can set the Handled property to true on the NewWindowRequested event's args, and no new window will be created. This is useful if you want to prevent opening windows or if you want to send new window opens to the default browser or somewhere else. In script the return value of window.open is null.
Or you can provide your own ICoreWebView2 via the NewWindow property. In this case you are responsible for and get to choose how to host that ICoreWebView2 in some manner. The ICoreWebView2 you provide as the NewWindow will be the target of the new window navigation and connected back up via script to the return value of the window.open call.
Because obtaining a new WebView2 may require asynchronous method calls, you can use the GetDeferral method on the event args to stop the completion of the window requested event until you call Complete on the deferral asynchronously later.
You can see a working sample of the add_NewWindowRequested event in our sample app.

SendMessage function to send text

I have a form and on the form I have a web browser and currently opened google.com on it.
Cursor is already focused on the search window.
I have been trying to SEND search Text to WebBrowser control using SendMessage but not working. Current code.
Const WM_SETTEXT As Integer = &HC
Dim hdle As IntPtr = WebBrowser1.Handle
SendMessage(hdle, WM_SETTEXT, 0, "test")
Why it's not sending text to google focused search tab ? How do I solve this ?
P.S : I don't want to use SendKeys or HTML method to SetText. I want to use Handler only.
The window handle of the Web browser control is not the window handle of the text edit control. So you are not sending the message to the control that you intend.
Indeed every mainstream browser that I know of does not use windowed controls. So that text window does not even have a window handle so no amount of work will make your basic concept successful.
What you are trying to do can best be achieved using UI Automation.

DELPHI MessageDlg Call from DLL disrupts Control Focus

Recent upgrade to RAD XE8.
I have a dll with several MessageDLg calls e.g. Warning/Information etc e.g.
procedure Information(Msg: string); stdcall;
begin
MessageDlg(Msg,mtInformation, [mbOK],0);
end;
I noticed last week the following:-
If I double click on a grid with a handler
begin
Information("I am here"); //in the dll
ens
the message is displayed but when I click and the message box disappears I can no longer click on the grid (Mouse wheel does work but not the buttons) (no response). If I click on a second control and then back on the grid all is well again.
I tried adding to the DLL
uses VCL.Forms;
procedure Information(Msg: string); stdcall;
begin
Application.Handle := GetForegroundWindow;
try
MessageDlg(Msg,mtInformation, [mbOK],0);
finally
Application.Handle := 0;
end;
end;
to no avail.
I have established the following:-
ih my app
CanFocus; //DBGrid1
MessageDlg(Msg,mtInformation, [mbOK],0);
CanFocus; //Still DBGrid
but in my app (calling the MessageDlg in the DLL via the function Information())
CanFocus; //DBGrid1
Information('Hi ya');
CanFocus; //MAINFORM
CanFocus only added for debug purposes
So the first dblclick on the DBGrid calls Information but subsequent dblclicks are not detected in the VCL (messages are visible via Windows
Detective).
in VC.LDBGids TCustomDBGrid.AcquireFocus:
Focused is True the first time and False subsequently, until I click a second control and then back on the DBGrid.
Does his make the issue clearer?
TIA
Ephraim
Edit: Setting the global variable UseLatestCommonDialogs to False solved the problem!
I'm having the same issue and posted a question on Embarcadero Forum. I hope the answer help you:
That is because none of the HWNDs that belong to the EXE are being
used as the owner for the modal dialog window, so it can't restore
focus correctly when closed. That is why you have to click on the grid
again to regain focus.
Raymond Chen has a whole series of articles on his "Old New Thing"
blog on MSDN that discuss issues related to modal window ownership (or
lack of).
That is because calling MessageDlg() inside the EXE has access to the
EXE's TApplication and TForm HWNDs to use as modal dialog owners. A
DLL does not have that same access.
I would suggest getting rid of MessageDlg() inside the DLL altogether.
Call the Win32 MessageBox() or TaskDialog() directly instead, then you
can provide whatever HWND you need as the owner window.
Remy Lebeau (TeamB)

VB6 - reading from keyboard in an ActiveX DLL

I have an ActiveX DLL which currently reads from a serial port. Now I want it to accept input from a USB device.
The USB device functions as a standard Human Interface Device. That is to say, if I open Notepad then the device's output will appear in Notepad as if it were typed on a keyboard.
Normally, I would capture Key Up/Down events, but I think that I need a form for that and my DLL does not have a form.
How can I capture that input?
[Update] I found this http://us.generation-nt.com/answer/anyone-know-how-read-keyboard-input-within-an-activex-dll-help-7934442.html# which claims to do it, but the code there won't work as is uses the AddressOf operator, which can only be used in a .BAS file, so not in an DLL .CLS
I am not even sure if I am looking for a system wide hook or application specific.
Hmmm, http://www.xtremevbtalk.com/showthread.php?t=77216 says "You can't implement a global WH_KEYBOARD hook in VB - it requires a standard (non ActiveX dll) as it has to be loaded into the address space of all the running applications."
[Upper date] So, maybe I can a form, make it 1x1 pixel and invisible and have a function GetTheData which shows the form modally and collects and returns the data - either getting keyboard input at form level or into a (n invisible) control then closes the form returning the input.
Would that work? If anyone posts a working example I will award a bounty (I would prefer that the form not be visible on the task bar and have no close button; the user should not be aware of it, or able to close it, it should close itself when it receives enough input from the USB attached HDI).
You can use RegisterRawInputDevices to monitor HID devices' input but this requires a window to listen for WM_INPUT message which means subclassing the window.
Here is a working sample project: UsbBarcodeSanner.zip
I think you have better option,
using uesr32.dll you can do this task easily,
refer this link
you will be able to use this function
Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vKey As Long) As Integer
This dll handles anything you want for user in windows.. refer Old Post
I hope this will help..

Launch an application and send it to second monitor

In VB 2008, I am using the class 'process' to launch and external application with a few parameters. Does anybody knows how can I send it programmatically to second monitor?
Also, is there any way to know how many monitors are activated?
Thanks.
You can locate your form on a different screen.
form.Location = Screen.AllScreens(1).Bounds.Location + new Point(100, 100)
When you launch an application, use the Process Handle to get the Window (hWnd). It's this hWnd value that windows API uses.
You will need to use the SetWindowRect method imported from User32.dll (see last link)
See also
Screen Class
VB .NET Dual Monitor
Get Window Handles Associated With Process in vb.net
Egghead Cage - hwnd position
MSDN - SetWindowRect API Call