Figure 2 CRACK OLE Control
CALLBCTL.H
// callbctl.h : Declaration of the CCallBackCtrl OLE control class.
// CCallBackCtrl : See callbctl.cpp for implementation.
class CCallBackCtrl : public COleControl
{
DECLARE_DYNCREATE(CCallBackCtrl)
// Constructor
public:
CCallBackCtrl();
CWordArray m_msglist; // List of registered messages
// Overrides
// We want first crack at the user messages!
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
// Drawing function
virtual void OnDraw(CDC* pdc, const CRect& rcBounds,
const CRect& rcInvalid);
// Persistence
virtual void DoPropExchange(CPropExchange* pPX);
// Reset control state
virtual void OnResetState();
// Implementation
protected:
~CCallBackCtrl();
DECLARE_OLECREATE_EX(CCallBackCtrl) // Class factory and guid
DECLARE_OLETYPELIB(CCallBackCtrl) // GetTypeInfo
DECLARE_PROPPAGEIDS(CCallBackCtrl) // Property page IDs
DECLARE_OLECTLTYPE(CCallBackCtrl) // Type name and misc status
// Message maps
//{{AFX_MSG(CCallBackCtrl)
// NOTE - ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
// Dispatch maps
//{{AFX_DISPATCH(CCallBackCtrl)
afx_msg short WatchMsg(short msg);
afx_msg long PtrValL(OLE_HANDLE lpPtr);
afx_msg short PtrValI(OLE_HANDLE lpPtr);
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
afx_msg void AboutBox();
// Event maps
//{{AFX_EVENT(CCallBackCtrl)
void FireCallback(short msg, long wParam, long lParam)
{FireEvent(eventidCallback,EVENT_PARAM(VTS_I2 VTS_I4 VTS_I4), msg, wParam, lParam);}
//}}AFX_EVENT
DECLARE_EVENT_MAP()
// Dispatch and event IDs
public:
enum {
//{{AFX_DISP_ID(CCallBackCtrl)
dispidWatchMsg = 1L,
dispidPtrValL = 2L,
dispidPtrValI = 4L,
eventidCallback = 1L,
//}}AFX_DISP_ID
};
};
CALLBCTL.CPP
// callbctl.cpp : Implementation of the CCallBackCtrl OLE control class.
#include "stdafx.h"
#include "cback.h"
#include "callbctl.h"
#include "callbppg.h"
#include "memory.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CCallBackCtrl, COleControl)
// Message map
BEGIN_MESSAGE_MAP(CCallBackCtrl, COleControl)
//{{AFX_MSG_MAP(CCallBackCtrl)
// NOTE - ClassWizard will add and remove message map entries
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG_MAP
ON_OLEVERB(AFX_IDS_VERB_EDIT, OnEdit)
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
// Dispatch map
BEGIN_DISPATCH_MAP(CCallBackCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CCallBackCtrl)
DISP_FUNCTION(CCallBackCtrl, "WatchMsg", WatchMsg, VT_I2, VTS_I2)
DISP_FUNCTION(CCallBackCtrl, "PtrValL", PtrValL, VT_I4, VTS_HANDLE)
DISP_FUNCTION(CCallBackCtrl, "PtrValI", PtrValI, VT_I2, VTS_HANDLE)
DISP_STOCKPROP_HWND()
//}}AFX_DISPATCH_MAP
DISP_FUNCTION_ID(CCallBackCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()
// Event map
BEGIN_EVENT_MAP(CCallBackCtrl, COleControl)
//{{AFX_EVENT_MAP(CCallBackCtrl)
EVENT_CUSTOM("Callback", FireCallback, VTS_I2 VTS_I4 VTS_I4)
//}}AFX_EVENT_MAP
END_EVENT_MAP()
// Property pages
// TODO: Add more property pages as needed. Remember to increase the count!
BEGIN_PROPPAGEIDS(CCallBackCtrl, 1)
PROPPAGEID(CCallBackPropPage::guid)
END_PROPPAGEIDS(CCallBackCtrl)
// Initialize class factory and guid
IMPLEMENT_OLECREATE_EX(CCallBackCtrl, "MSJ.Callback.Control",
0x3d76aaa0, 0x17aa, 0x11cf, 0xa0, 0x18, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0)
// Type library ID and version
IMPLEMENT_OLETYPELIB(CCallBackCtrl, _tlid, _wVerMajor, _wVerMinor)
// Interface IDs
const IID BASED_CODE IID_DCallBack =
{ 0x3d76aaa1, 0x17aa, 0x11cf, { 0xa0, 0x18, 0x44, 0x45, 0x53,
0x54, 0x0, 0x0 } };
const IID BASED_CODE IID_DCallBackEvents =
{ 0x3d76aaa2, 0x17aa, 0x11cf, { 0xa0, 0x18, 0x44, 0x45, 0x53,
0x54, 0x0, 0x0 } };
// Control type information
static const DWORD BASED_CODE _dwCallBackOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CCallBackCtrl, IDS_CALLBACK, _dwCallBackOleMisc)
// CCallBackCtrl::CCallBackCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CCallBackCtrl
BOOL CCallBackCtrl::CCallBackCtrlFactory::UpdateRegistry(BOOL bRegister)
{
if (bRegister)
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid, m_lpszProgID,
IDS_CALLBACK, IDB_CALLBACK,
TRUE, // Insertable
_dwCallBackOleMisc,
_tlid, _wVerMajor,
_wVerMinor);
else
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
// CCallBackCtrl::CCallBackCtrl - Constructor
CCallBackCtrl::CCallBackCtrl()
{
InitializeIIDs(&IID_DCallBack, &IID_DCallBackEvents);
}
// CCallBackCtrl::~CCallBackCtrl - Destructor
CCallBackCtrl::~CCallBackCtrl()
{
}
// CCallBackCtrl::OnDraw - Drawing function
void CCallBackCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
// Always hide the window - we need a handle, but not a displayed
// window.
if (m_hWnd != NULL)
::ShowWindow(m_hWnd, SW_HIDE);
pdc->Rectangle(rcBounds);
}
// CCallBackCtrl::DoPropExchange - Persistence support
void CCallBackCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
}
// CCallBackCtrl::OnResetState - Reset control to default state
void CCallBackCtrl::OnResetState()
{
COleControl::OnResetState(); // Resets defaults found in DoPropExchange
}
// CCallBackCtrl::AboutBox - Display an "About" box to the user
void CCallBackCtrl::AboutBox()
{
CDialog dlgAbout(IDD_ABOUTBOX_CALLBACK);
dlgAbout.DoModal();
}
// CCallBackCtrl message handlers
short CCallBackCtrl::WatchMsg(short msg)
{
// Control method - the user can add a message for the control
// to watch for.
m_msglist.Add(msg);
return msg;
}
// When we get a registered message, call FireCallback(msg, wParam, lParam)
LRESULT CCallBackCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
for (int m=0; m < m_msglist.GetSize(); m++)
{
if (m_msglist[m] == message)
FireCallback(message, wParam, lParam);
}
return COleControl::WindowProc(message, wParam, lParam);
}
// Special bonus for people who actually read these code samples!
// The following functions take a long int pointer value and return
// the long integer or short integer it points to. These can be
// useful depending on the information the Callback function sends
// back to wParam and lParam.
long CCallBackCtrl::PtrValL(OLE_HANDLE lpPtr)
{
return *((LPLONG) lpPtr);
}
short CCallBackCtrl::PtrValI(OLE_HANDLE lpPtr)
{
return *((LPINT) lpPtr);
}
Figure 3 VBTRAY
VBTRAY.FRM
.
.
.
'====================================================
' When the user clicks on the Create button, do this
Private Sub btnCreate_Click()
Dim tnd As NOTIFYICONDATA ' The Shell_NotifyIcon data structure
' Alternate between Create and Delete handling
If btnCreate.Caption = "Create" Then
' Fill in tnd with appropriate values
tnd.szTip = edtTip.Text & Chr$(0)
' Flags: the message, icon, and tip are valid and should be
' paid attention to.
tnd.uFlags = NIF_MESSAGE + NIF_ICON + NIF_TIP
tnd.uID = 100
tnd.cbSize = Len(tnd)
' The window handle of our callback control
tnd.hwnd = CBWnd.hwnd
' The message CBWnd will receive when there's an icon event
tnd.uCallbackMessage = WM_USER + 1
tnd.hIcon = picIcon.Picture
' Make the callback window wait for our defined message
CBWnd.WatchMsg (WM_USER + 1)
' Add the icon to the taskbar tray
rc = Shell_NotifyIcon(NIM_ADD, tnd)
' Flip the button's name
btnCreate.Caption = "Remove"
ElseIf btnCreate.Caption = "Remove" Then
' On remove, we only have to give enough information for Windows
' to locate the icon, then tell the system to delete it.
tnd.uID = 100
tnd.cbSize = Len(tnd)
tnd.hwnd = CBWnd.hwnd
tnd.uCallbackMessage = WM_USER + 1
rc = Shell_NotifyIcon(NIM_DELETE, tnd)
' Ready to create a new one!
btnCreate.Caption = "Create"
End If
End Sub
'=========================================
' btnIcon changes the icon in the tray
Private Sub btnIcon_Click()
Dim tnd As NOTIFYICONDATA
' Fill the data structure with necessary information, including
' the icon we get from the form's picture box
tnd.uFlags = NIF_ICON
tnd.uID = 100
tnd.cbSize = Len(tnd)
tnd.hwnd = CBWnd.hwnd
tnd.uCallbackMessage = WM_USER + 1
tnd.hIcon = picIcon.Picture
' Call the modify part of the function to change the elements indicated
' by the uFlags Type member above - in this case, just the icon.
rc = Shell_NotifyIcon(NIM_MODIFY, tnd)
End Sub
'=========================================
' btnLoad shows the Open common dialog, then retrieves the chosen filename
' and tries to load a picture from it. This can be an icon or an appropriately
' bitmap.
Private Sub btnLoad_Click()
ComDlg.ShowOpen
picIcon.Picture = LoadPicture(ComDlg.filename)
End Sub
'=========================================
' btnTip changes the Tip property of the icon, similar to the btnIcon
' changing the icon.
Private Sub btnTip_Click()
Dim tnd As NOTIFYICONDATA
' The tip is going to be important
tnd.uFlags = NIF_TIP
tnd.uID = 100
tnd.cbSize = Len(tnd)
tnd.hwnd = CBWnd.hwnd
tnd.uCallbackMessage = WM_USER + 1
' Get the new tip from the onscreen edit box. This has to have a null
' character appended to it or the tip will appear as a string with as
' many trailing spaces as there are in the fixed-length string.
tnd.szTip = edtTip.Text & Chr$(0)
rc = Shell_NotifyIcon(NIM_MODIFY, tnd)
End Sub
'=========================================
' CBWnd_CallBack is called by the Cback control any time it receives
' a window message specified by a previous WatchMsg call to it. It
' provides the VB programmer the original msg/wParam/lParam intact. (These
' may at times be pointers to values instead of actual values; it is up to
' the programmer to know when this will occur and adjust his code accordingly.
Private Sub CBWnd_CallBack(ByVal msg As Integer, ByVal wParam As Long, ByVal lParam As Long)
' If the user has pressed the mouse button on the icon, pop up a message box
If (lParam = WM_LBUTTONDOWN) Then
MsgBox "You clicked on the tray icon!", vbOKOnly, "Shell_NotifyIcon callback"
End If
End Sub
'============================================================
' The basic Form_Load - this provides a default icon and string
' for the VB program to set the tray icon.
Private Sub Form_Load()
edtTip.Text = "Generic tip string."
picIcon.Picture = Me.Icon
End Sub
VBTRAY.BAS
Attribute VB_Name = "Module1"
Public Const WM_USER = &H400
Public Const NIF_ICON = &H2
Public Const NIF_MESSAGE = &H1
Public Const NIF_TIP = &H4
Public Const NIM_ADD = &H0
Public Const NIM_DELETE = &H2
Public Const NIM_MODIFY = &H1
Public Const WM_MOUSEMOVE = &H200
Public Const WM_LBUTTONUP = &H202
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONDBLCLK = &H203
Type NOTIFYICONDATA
cbSize As Long
hwnd As Long
uID As Long
uFlags As Long
uCallbackMessage As Long
hIcon As Long
szTip As String * 64
End Type
Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long