在ActiveX中使用GDI+和在其它应用程序中使用基本上是相同的,但是有一个非常重要的不同就是启动和停止GDI+的问题。在一个window应用程序中,我们一般在程序开始时启用GDI+,在程序退出时停止它。这样的方法在ActiveX中并不适用,会出现多次加载的情况。在我的测试中,如果GDI+在继承了COleControl类的构造函数中调用,在析构函数中停止,那么每次都是好用的。
下面的程序直接写了一个类来完成GDI+的启用和停止,它确保在每个进程中只调用一次Gdiplus::GdiplusStartup。
class InitGDIPlus {
private:
HANDLE m_hMap;
bool m_bInited, m_bInitCtorDtor;
ULONG_PTR m_gdiplusToken;
Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;
long m_initcount;
public:
// Constructor offers the ability to initialize on construction, or delay until needed.
InitGDIPlus(bool bInitCtorDtor = false) : m_bInitCtorDtor(bInitCtorDtor),
m_bInited(false), m_hMap(NULL), m_gdiplusToken(NULL),
m_gdiplusStartupInput(NULL), m_initcount(0)
{
if (m_bInitCtorDtor) {
Initialize();
}
}
// If GDI+ has not been explicitly Deinitialized, do it in the destructor
virtual ~InitGDIPlus() {
if (m_bInitCtorDtor) {
Deinitialize();
}
}
//这个函数基于当前的进程创建一个文件映射,如果映射已经存在我们就知道这个类已经启用
//GDI+了,不过不存在,则启用它
void Initialize() {
if (!m_bInited) {
char buffer[1024];
sprintf(buffer, "GDIPlusInitID=%x", GetCurrentProcessId());
m_hMap = CreateFileMapping((HANDLE) INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE | SEC_COMMIT, 0, sizeof(long), buffer);
if (m_hMap != NULL) {
// We might have a winner
if (GetLastError() == ERROR_ALREADY_EXISTS) {
CloseHandle(m_hMap);
} else {
// Yes, we have a winner
m_bInited = true;
Gdiplus::GdiplusStartup(&m_gdiplusToken,
&m_gdiplusStartupInput, NULL);
TRACE("Inited GDIPlus/n");
}
}
}
m_initcount++;
}
//这个函数没有任何窍门,如果类已经启用的GDI+,那么在初始化次数达到0时才能被关闭
void Deinitialize()
{
m_initcount--;
if (m_bInited && m_initcount == 0) {
TRACE("GDIPlus shutdown/n");
Gdiplus::GdiplusShutdown(m_gdiplusToken);
CloseHandle(m_hMap);
m_bInited = false;
}
}
};
static InitGDIPlus GDI_Plus_Controler;
CGDIPlusControlCtrl::CGDIPlusControlCtrl() : m_isClicked(false), m_center(50, 50)
{
InitializeIIDs(&IID_DGDIPlusControl, &IID_DGDIPlusControlEvents);
GDI_Plus_Controler.Initialize(); //GDI_Plus_Controler 为静态全局变量
}
/
// CGDIPlusControlCtrl::~CGDIPlusControlCtrl - Destructor
CGDIPlusControlCtrl::~CGDIPlusControlCtrl()
{
GDI_Plus_Controler.Deinitialize(); //GDI_Plus_Controler为静态全局变量
}