How to resize an ActiveX window or control.

June 24th, 2008

Resizing an ActiveX window is hard. That’s all there is to it. If you try using the nifty SetWindowPos function, you will indeed see the ActiveX window resize, but as soon as you try using it, it will pop back to it’s original size. To successfully resize it, involves using COM, smart pointers and an obscure object known as IUnknownPtr. Heh, IUnknownPtr, brilliant name! One things for sure, it’s unknown to me!

Building this function, and getting it to work and compile was one of the worst programming experiences I have ever had. COM and smart pointers are some of the most infuriating subjects in the world of computer programming. All I needed was a little information to get started, and there simply was little to no information available online (about defining the IUnknownPtr object) . I thankfully, after hours of searching, found an obscure forum post, showing how to define the IUnknownPtr object, or whatever it is. Something so simple, yet so insanely difficult to find. I don’t mind telling you that this experience, plus a few others, have left a very bad taste in my mouth, when it comes to COM. There is simply no reason, in this day and age, for something like COM, to be so convoluted and archaic. Avoid COM, it’s bad news.

Unfortunately for us however, using COM is the only way to resize an ActiveX window, so we must use the wretched thing. Well, here is what I finally came up with, enjoy.

// This is the magical line that defines IUnknownPtr, simply unbelievable how hard this was to find.
typedef _com_ptr_t<_com_IIID > IUnknownPtr;  

void SizeActiveXWindow(CWnd &ctrl, CRect newRect)
{
	IUnknownPtr unk(ctrl.GetControlUnknown(), true);
	IOleObjectPtr oleo=unk; 

	IOleClientSitePtr olecs;
	if (oleo!=0) oleo->GetClientSite(&olecs);
	IOleInPlaceSitePtr olips=olecs;

	ctrl.MoveWindow(newRect); 

	if (olips!=0) olips->OnPosRectChange(&newRect);
}

How to launch another program, and wait for it to finish.

June 23rd, 2008

Here is some handy code for launching another program, and waiting for it to finish.

// LaunchEx will launch the filename specified, allowing you to specify command line parameters,
// whether to wait for the launched program to finish, and whether to show the launched program.
// The exit code of the launched program is returned, when you set wait to TRUE.
DWORD LaunchEx(CString filename, CString commandline, BOOL wait, BOOL show)
{
	DWORD exitcode=-1;

	// Launch and wait for process using ShellExecuteEx.
	if (wait)
	{
		SHELLEXECUTEINFO ShExecInfo = {0};
		ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
		ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
		ShExecInfo.hwnd = NULL;
		ShExecInfo.lpVerb = NULL;
		ShExecInfo.lpFile = filename;
		ShExecInfo.lpParameters = commandline;
		ShExecInfo.lpDirectory = NULL;
		if (show) ShExecInfo.nShow = SW_SHOW;
		else ShExecInfo.nShow = SW_HIDE;
		ShExecInfo.hInstApp = NULL;
		ShExecInfo.hProcess = NULL;
		ShellExecuteEx(&ShExecInfo);
		if (ShExecInfo.hProcess)
		{
			WaitForSingleObjectMessageLoop(ShExecInfo.hProcess);
			GetExitCodeProcess(ShExecInfo.hProcess, &exitcode);
			CloseHandle(ShExecInfo.hProcess);
		}
	}
	else if (commandline!="") Launch(filename+" "+commandline);
	else Launch(filename);

	return(exitcode);
}

// Launch will simply open or run any file specified, it returns immediately.
void Launch(CString filename)
{
	int pos;
	CString parameters;

	if ((pos=filename.Find(".exe"))!=-1)
	{
		parameters=filename.Mid(pos+4);
		filename=filename.Left(pos+4);
	}

	if (parameters!="") ::ShellExecute(NULL,"open",filename,parameters,"", SW_SHOW);
	else ::ShellExecute(NULL,"open",filename,"","", SW_SHOW);
}

// Will wait for a single object to become signaled, in the meantime, pump messages.
BOOL WaitForSingleObjectMessageLoop(HANDLE hEvent)
{
	DWORD dwRet;
	MSG msg;

	while (1)
	{
		dwRet = MsgWaitForMultipleObjects(
			1, // One event to wait for.
			&hEvent, // The array of events.
			FALSE, // Wait for one event.
			INFINITE, // Timeout value.
			QS_ALLINPUT // Any message wakes up.
			);
		if (dwRet==WAIT_OBJECT_0)
		{
			// The event was signaled, return
			return(TRUE);
		}
		else if (dwRet==WAIT_OBJECT_0+1)
		{
			// There is a window message available. Dispatch it.
			while (PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else
		{
			// Something else happened. Return.
			return FALSE;
		}
	}
}

How to pop up a window, no matter what.

June 22nd, 2008

Several years ago, Microsoft decided it would be a good idea to prevent applications that were not already in focus, from being able to grab the focus and pop up their window in front of the user.  Obviously this was done to help curb nasty nefarious programs from being irritating hogs, always popping up in your face.

The problem is that sometimes, you have a legitimate reason for wanting to pop up a window in front of the user. For instance you may have a scheduler, that needs to remind the user of something, or you may want to tell the user about an important error that needs their attention immediately, the list goes on.

Well, popping a window up seems trivial, and the actual solution is, but figuring out the magic spell that makes it happen is not. I spent days and days, pouring over the internet looking for a solution that actually worked. I found the solution in an obscure forum post, who mentioned the magical use of the keybd_event function. Apparently, if you call keybd_event, with all zeros for values, it somehow allows your application to grab the attention of Windows, and allows a subsequent call to SetForegroundWindow to work like god intended it to. Well I tried it, and it worked. So very cool.

Here is a method that will pop up and set the focus of any window:

void PopWindow(CWnd &wnd)
{
   // Show target window if it is hidden.
   wnd.ShowWindow(SW_SHOW);

   // Magic keyboard event that pops window up.
   keybd_event( 0, 0, 0, 0 );

   // Set window to the foreground.
   SetForegroundWindow(wnd.GetSafeHwnd());

   // Set focus to target window.
   wnd.SetFocus();
}

Welcome

June 19th, 2008

This site is intended to provide useful chunks of code, so you can get whatever it is you are working on… working. A few things that this site is not intended to do: have a lengthy egg head conversation about how a particular piece of code works; expect you to already know some hidden secret about how something works.

At the end of the day, this site will hopefully help you solve a problem quickly and easily. Often I have had a problem, and all I wanted was a clean, quick piece of code I could cut and paste. I hope this collection of code snippets, that I have both written and collected, can help you quickly solve a problem you may have.

I’m just an average joe programmer, trying to get a problem solved so I can get my work done.

For years I have relied on the good advice of other programmers, who have shared their expertise through websites and forums, helping out others just like themselves. Though many code snippets presented here were designed by myself alone, others owe their existence to the hard work and examples produced by other programmers. So to them I say thank you. I hope this site can in some way repay the generous sharing of knowledge I have so often enjoyed.

Pigmaei gigantum humeris impositi plusquam ipsi gigantes vident…

Dwarfs standing on the shoulders of giants: “One who develops future intellectual pursuits by understanding the research and works created by notable thinkers of the past”