[ Home | FAQ | OCX Book | Sites ]  

OLE Controls Frequently Asked Questions
Non-Visual Control Questions

Last Update: April 23, 1996

Why can't I get a timer to work in my control?

Timers require the use of a true HWND within your control and non-visual controls do not have a window created for them by default. One method that I've used is to override the COleControl::OnSetClientSite method. This method is called very early in the creation of a control within the container. Here's an example:

// Ensure the control has a valid HWND as soon as it
// is placed on the container
void CYourCtrl::OnSetClientSite()
{
   // We only need the window at run-time
   if ( AmbientUserMode() )
      RecreateControlWindow();
}

RecreateControlWindow is very useful in this situation as it creates a default window for your control. And that's all that you need in order to implement a timer for your non-visual control. Of course there are some decisions you need to make regarding where you should start and stop the timer.

Actually, the code above will work, but it is not the most efficient way to do it. Visual Basic as well as other containers may call OnSetClientSite multiple times when instantiating the control. Visual Basic actually calls SetClientSite twice, when the control is initially created and later when the control is destroyed. Also the AmbientUserMode property isn't valid unless there is a IDispatch set up with the container. The code below takes all this into consideration. It ensures that RecreateControlWindow is only called once and ensures that the container is in design mode.

// Ensure the control has a valid HWND as soon as it
// is placed on the container
void CYourCtrl::OnSetClientSite()
{
   // We only need the window at run-time
   // Only call recreate when there is a valid ambient dispatch
   if ( m_ambientDispDriver.m_lpDispatch && AmbientUserMode() )
      RecreateControlWindow();
}

Back to top


How do I draw my non-visual control as an icon in design mode?

The OLEMISC_INVISIBLEATRUNTIME MiscStatus flag indicates to the container that your control does not require a run-time representation. By setting this flag, the container will not call your control's OnDraw method at run-time, but it will still be called during the design-phase. This makes it easy for the control user to keep track of the control and allows easy access to its properties. Most non-visual controls provide an iconic representation during the design phase. The code below uses the control's toolbar bitmap to provide a design-time rendering.

////////////////////////////////////////////////////////
// CPipeCtrl::OnDraw - Drawing function
void CPipeCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
   CBitmap bitmap;
   BITMAP  bmp;
   CPictureHolder picHolder;
   CRect rcSrcBounds;

   // Load the toolbar bitmap
   bitmap.LoadBitmap( IDB_PIPE );
   bitmap.GetObject( sizeof(BITMAP), &bmp );
   rcSrcBounds.right = bmp.bmWidth;
   rcSrcBounds.bottom = bmp.bmHeight;

#ifdef _WIN32
   ::DrawEdge( pdc->GetSafeHdc(),
               CRect( rcBounds ),
               EDGE_RAISED,
               BF_RECT | BF_ADJUST );
#endif

   picHolder.CreateFromBitmap( (HBITMAP)bitmap.m_hObject, NULL, FALSE );

   // Render the control
   picHolder.Render( pdc, rcBounds, rcSrcBounds );
}
CPipeCtrl::CPipeCtrl()
{
   InitializeIIDs(&IID_DPipe, &IID_DPipeEvents);
   // Set the control's initialize size
   SetInitialSize( 28, 26 );
...
}

The default size of a control is much larger than a typical icon (100x150) so a call to SetInitialSize in the control's constructor sets the initial size to 28x26. The OnSetExtent method can also be overridden to ensure that the control maintains a specific size. See the control size restriction question under the General FAQ section for more details.

Back to top


Typical Disclaimer: This FAQ is copyright (c) 1996 by Tom Armstrong. You have the right to copy and distribute this file in any way you see fit as long as this paragraph is included with the distribution. No warranties or claims are made as to the validity of the information contained herein. So use it at your own risk


Send mail to Tom - toma@sky.net