Is it possible to embed one application in another application in Windows? - windows

I'm writing a Windows application in Visual C++ 2008 and I want to embed the calculator (calc.exe) that comes with Windows in it. Does anyone know if that is possible, and if it is, can you give me hints on how I could achieve that?

Yes, it's possible to embed the calc in your own application but it will still run in it's own process space. There may also be some restrictions imposed by UAC but that will depend on how calc is launched. All you need to do is change the parent of the main calc window and change it's style to WS_CHILD.
void EmbedCalc(HWND hWnd)
{
HWND calcHwnd = FindWindow(L"CalcFrame", NULL);
if(calcHwnd != NULL)
{
// Change the parent so the calc window belongs to our apps main window
SetParent(calcHwnd, hWnd);
// Update the style so the calc window is embedded in our main window
SetWindowLong(calcHwnd, GWL_STYLE, GetWindowLong(calcHwnd, GWL_STYLE) | WS_CHILD);
// We need to update the position as well since changing the parent does not
// adjust it automatically.
SetWindowPos(calcHwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
}

Microsoft has various technologies to support embedding, most famously OLE which is a COM-based technology. This is, for example, how you can embed an Excel spreadsheet in your application. However, I'm fairly certain that calc does not implement any of the required interfaces for that to happen.
So that only leaves you with hacky solutions, like trying to launch it yourself and play games with the window hierarchy, or try to present it to users and then copy the results out through the clipboard, etc. This is all technically possible, but not a good idea. In fact, it's probably more difficult than just writing your own calculator app... depending on what you want to to enable users to do. If you explain why you want to do this someone may have some better solutions to propose.

Related

MFC dialog form on the top of all applications

Is it possible create MFC form that cold stay on the top of all applications on PC not allowing to do anything else without entering required information.
Win32 doesn't support system-modal dialogs any more, as far as I'm aware. This is a relic from 16 bit Windows versions.
You can try yourself with a MB_SYSTEMMODAL type MessageBox.
Closest thing would be to utilize a screen-sized window to display a dimmed desktop background while your dialog is shown. This simulates the behaviour of the user account control -- except that you still can switch tasks.
You can obtain something similar setting your window on "TopMost". You can do it on property sheet in design mode, or programmatically with this line:
SetWindowPos( pWnd->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE );
Hope this will fit your needs.

Minimize/restore windows programmatically skipping the animation effect

I need to perform several operations on a list of windows (minimize some of them, restore others) in order to switch between two or more set of windows at once.
The problem with this are those animations you can see when minimizing and restoring a window. The whole process look terrible with all those animations going in and out, up and down.
I cannot, however, disable those animations because this is for other computers and i dont want to change other people's settings, plus those animations are actually useful when you minimize/restore one window only (i.e. when YOU do it manually) because you can see what is happening, but for doing it programmatically on several windows at a time, it's not nice.
I'm currenlty using the SendMessage function to send the WM_SYSCOMMAND message with params SC_MINIMIZE/SC_RESTORE. I dont know whether there is another way.
So, the question:
How can I minimize/restore a window programatically without the animation effect??
PS: The programming language is not important. I can use any language that's nessesary for accomplishing this.
SetWindowPlacement with SW_SHOWMINIMIZED or SW_RESTORE as appropriate for showCmd in WINDOWPLACEMENT seems to bypass window animation. I'd keep an eye on the functionality for future versions of the OS though since documentation does not mention anything about animation.
How about Hide > Minimize > Show ?
You could temporarily disable the animations and then restore the user's original setting.
class WindowsAnimationSuppressor {
public:
WindowsAnimationSuppressor() : m_suppressed(false) {
m_original_settings.cbSize = sizeof(m_original_settings);
if (::SystemParametersInfo(SPI_GETANIMATION,
sizeof(m_original_settings),
&m_original_settings, 0)) {
ANIMATIONINFO no_animation = { sizeof(no_animation), 0 };
::SystemParametersInfo(SPI_SETANIMATION,
sizeof(no_animation), &no_animation,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
m_suppressed = true;
}
}
~WindowsAnimationSuppressor() {
if (m_suppressed) {
::SystemParametersInfo(SPI_SETANIMATION,
sizeof(m_original_settings),
&m_original_settings,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
}
private:
bool m_suppressed;
ANIMATIONINFO m_original_settings;
};
void RearrangeWindows() {
WindowsAnimationSuppressor suppressor;
// Rearrange the windows here ...
}
When the suppressor is constructed, it remembers the user's original setting and turns off the animation. The destructor restores the original settings. By using a c'tor/d'tor, you ensure that the user's settings are restored if your rearranging code throws an exception.
There is a small window of vulnerability here. In theory, the user could change the setting during the operation, and then you'll slam the original setting back. That's extremely rare and not really that bad.

How to find main HWND handle of MFC-using parent process

I have a DLL file that is running under a parent piece of software. The parent software uses MFC and displays a main GUI window. What I want to do is create my own little modeless dialog box to pop up on the screen and sit right next to the main window. To do this I think I need the HWND of the parent's main window so I can find it's RECTangle and then move my DLL's window to where I want it.
If at all possible, I'd like not to change the source of the parent. How could I do this?
A second, possibly related, question is whether I should use MFC, or plain windows API, to create my DLL's dialog box. I want the method that will be easier to get it going, and I have read on MSDN that I may need the parent MFC application to send me messages for my MFC to work, which I'd rather not do.
I don't know if you can create an MFC dll that can find MFC objects created in another module. I'm pretty sure that MFC can be used to create dialogs from DLLs, regardless of whether or not MFC is used in the application.
That said, if you are not already an MFC expert, and have no real wish to become one, creating a dialog box from a dll is quite easy. MFC's CDialog is really a thin wrapper over CreateDialog so you don't gain much.
I can think of at least two approaches to find the application window if the app/dll interface doesn't hand it over:
Use FindWindow to locate the window based on its title, or classname. As frameworks like MFC sometimes generate window classnames dynamically this might be problematic.
Use EnumWindows to enumerate all top level windows. GetWindowThreadProcessId can test if it belongs to the current process.
Call GetGUIThreadInfo on the main thread. This gets you a bunch of HWNDs. Pick any valid one (not all values may be filled) and find its top level ancestor with GetAncestor(GA_ROOT). Unlike EnumWindows, this doesn't require enumeration, and unlike FindWindow this doesn't require specialized knowledge
For obtaining the PID of the parent — not the HWND — look at this that I found on http://www.codeexperts.com/showthread.php?1380-get-parent-process-id-from-child-process-id&p=2845&viewfull=1#post2845
DWORD GetParentProcessID(DWORD dwProcessID)
{
DWORD dwParentProcessID = -1 ;
HANDLE hProcessSnapshot ;
PROCESSENTRY32 processEntry32 ;
hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) ;
if(hProcessSnapshot != INVALID_HANDLE_VALUE)
{
processEntry32.dwSize = sizeof(PROCESSENTRY32) ;
if(Process32First(hProcessSnapshot, &processEntry32))
{
do
{
if (dwProcessID == processEntry32.th32ProcessID)
{
dwParentProcessID = processEntry32.th32ParentProcessID ;
break ;
}
}
while(Process32Next(hProcessSnapshot, &processEntry32)) ;
CloseHandle(hProcessSnapshot) ;
}
}
return dwParentProcessID ;
}

how to find type of GDI

i am beginner in win 32 api . i try use win 32 api for create an onscreen keyboard . I can give handle of window and components by click but how to realize type of these and i want set text only on text box and editable components
i try to use GetWindowInfo() and try use atomWindowType of window for realize type of that but this is not use full for this goal because this change on each restart of OS.
(click is handle of window)
WINDOWINFO pwi = new WINDOWINFO(); USER32INST.GetWindowInfo(click, pwi); if (pwi.atomWindowType != -15891) { setLastclick(click); } tnx
You are not going to be able to achieve what you desire, in full generality it is not realistically possible.
A window's type (or class) is essentially determined by its WndProc. You can use GetClassName and its ilk to help you identify some standard window classes, but as you have already discovered, most real-world apps will not use these standard classes.
So, although in theory, you could analyse the code behind the WndProc at runtime, in practice this is not remotely feasible.

Can a window be always on top of just one other window?

In Windows, is it possible to set window A such that it is always on top of window B, yet allow other windows to work as normal and appear over the top of both, when active.
In other words, I want a parent-child relationship between two windows. Can this be done without making window A a child of window B, MDI-style? Window B isn't mine (Internet Explorer), and screws my dialog A's graphics up when I try to achieve this with SetParent.
I thought I'd cracked it with this idea from an MSDN forum post, but alas windows A is still always on top of everything, not just window B.
// Place window A on top
SetWindowPos(hWndWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
// Place window B underneath it
SetWindowPos(hWndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
Is it possible?
Wouldn't creating an ownership relationship do the trick?
SetWindowLong(hwndChild, GWL_HWNDPARENT, hwndOwner)
The windows can be in different processes and you can call this from any process. This will ensure that the child window is always above the owner window. This is different than SetParent which actually creates a Parent / Child relationship. Read through this article (its from 1993 but still mostly correct) to see the distinction between ownership and parenting.
When your window's Z-order (or size or position) is changing, it should receive a WM_WINDOWPOSCHANGING message. If you process that message, you have an opportunity to modify the final Z-order (or size or position) to which the window is moved.
To illustrate, in hWndA's window procedure:
case WM_WINDOWPOSCHANGING:
DefWindowProc(hWnd, msg, wParam, lParam);
WINDOWPOS *p = (WINDOWPOS*)lParam;
p->hwndInsertAfter = hWndB;
p->flags &= ~SWP_NOZORDER;
return 0;
should insert hWndA after hWndB in the Z-order any time hWndA's position changes.
Until Vista, one way to do it would have been to use SetWindowsHookEx, and hook the WH_CBT or WH_CALLWNDPROC hook, and then take appropriate action when you detect the Z order changing. However this doesn't work with Vista (as far as I can tell from googling).
The only other solution I can think of is to set up a timer to fire every few seconds, and then when you receive a WM_TIMER, you interrogate the system using GetNextWindow to find out which window is behind yours. If it's not IE, then call SetWindowPos to position your window above IE (I assume you have a HWND for the IE window you care about - remember there can be multiple IE windows).
This will cause problems if people try to bring your window to the front - it will flip back to being just above IE. In this case, in your code you could handle WM_ACTIVATE and try to change the Z-order of IE's window so it's below your window (call SetWindowPos to move IE's window so it's above the window that is currently below your window). This solution may be fraught with problems as Windows may try to prevent you messing with the windows of another process, for security reasons. On the other hand, the MSDN docs for SetWindowPos don't explicitly mention that you can't manipulate the windows of another process. There may be obscure limitations though.
Even with this timer hack, you're going to effectively have a busy-waiting loop in your app (with the frequent WM_TIMER messages) and this is generally a bad thing to do, especially for battery life of laptops etc. (because you prevent the CPU from entering a sleep state, and so on).
I'd say there's no good way of doing this, and anything you're likely to get working will be brittle and cause problems. I strongly recommend not trying to do it. Is it possible to make your program into some kind of plug-in or toolbar for IE instead?
NB Be particularly aware that SetWindowsHookEx imposes a performance penalty at a system-wide level if you go down this route.
Maurice's answer is the best out of what's here but is missing an important step. When you call show on your window that you want as the overlay, you need to call the show method that has the parameter. You'll need to define a class that implements the IWin32Window interface and just make a new instance of that. The only thing that interface cares about is the Handle so just set that to the handle of the IE window and it should work pretty well
If the parent-child relationship is made by yourself with the SetWindowPos() function, your desire can be implemented.
Can you access the Z-order of the windows?
I cannot recall the default z-order of windows, but I think it is 1. You might be able to set IE to a -1 and your app to 0.
Try this:
// Place window A on top of window B
SetWindowPos(hWndA, hWndB, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
The second window handle parameter specifies the next window down in the Z order.
Note this doesn't actually change the window parent-child relationships - but you can simulate it.

Resources