-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAdvertise.cpp
352 lines (308 loc) · 18.8 KB
/
Advertise.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
// Advertise.cpp : implementation file
//////////////////////////////////////////////////
//类名:CAdvertise
//功能:广告对话框实现
//作者:徐景周(Johnny Xu, xujingzhou2016@gmail.com)
//组织:未来工作室(Future Studio)
//日期:2001.12.1
//////////////////////////////////////////////////
#include "stdafx.h"
#include "helptip.h"
#include "Advertise.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// Advertise dialog
CAdvertise::CAdvertise(CWnd* pParent /*=NULL*/)
: CDialog(CAdvertise::IDD, pParent)
{
//{{AFX_DATA_INIT(Advertise)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CAdvertise::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(Advertise)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAdvertise, CDialog)
//{{AFX_MSG_MAP(Advertise)
ON_WM_ERASEBKGND()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// Advertise message handlers
// ---------------------------------------------------------
// 名称: OnInitDialog
// 功能: 初始化广告对话框
// 变量: 无
// 返回: TRUE --成功,FALSE -- 失败
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
BOOL CAdvertise::OnInitDialog()
{
CDialog::OnInitDialog();
//初始置窗体大小为背景位图大小
CRect windowRect,m_Rect,DeskTopWnd;
windowRect.SetRect(0,
0,
BACKWIDTH ,
BACKHEIGHT );
//计算广告窗体到系统区位置
m_Rect=GetTrayWndRect(); //注:暂只限任务条在屏幕下方时
::GetWindowRect(::GetDesktopWindow(),&DeskTopWnd);
windowRect.top =DeskTopWnd.bottom -m_Rect.Height()-windowRect.Height();
windowRect.bottom =DeskTopWnd.bottom-m_Rect.Height();
windowRect.right =m_Rect.right;
windowRect.left = windowRect.right - BACKWIDTH;
//置窗体为显示及其位置
MoveWindow(windowRect,FALSE);
//装入手形光标
m_Cursor = ::LoadCursor(AfxGetResourceHandle(),MAKEINTRESOURCE(IDC_HAND));
//将广告位图透明化
m_bmpDraw.LoadBitmap(IDB_ADVERTISE);
CWindowDC dc(this);
TransparentRegion(&dc);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
//********************************************************************************
//* 名称:TransparentRegion()
//* 作者:徐景周(jingzhou_xu@163.net)
//* 功能:将窗体背景透明化(新的透明算法)
//********************************************************************************
void CAdvertise::TransparentRegion(CDC *pDC)
{
HRGN hRgn = NULL;
CBitmap &cBitmap=m_bmpDraw;
CRect cRect;
GetWindowRect(&cRect);
CPoint ptOrg=cRect.TopLeft();
// 获取位图大小
BITMAP bm;
cBitmap.GetObject(sizeof(bm),&bm);
CRect rcNewWnd=CRect(ptOrg,CSize(bm.bmWidth,bm.bmHeight));
// 创建兼容DC,只便扫描它的元素
HDC hMemDC = CreateCompatibleDC(NULL);
if (hMemDC)
{
// 创建一32位位图,并放到兼容DC中
BITMAPINFOHEADER RGB32BITSBITMAPINFO = {
sizeof(BITMAPINFOHEADER), // biSize
bm.bmWidth, // biWidth;
bm.bmHeight, // biHeight;
1, // biPlanes;
32, // biBitCount
BI_RGB, // biCompression;
0, // biSizeImage;
0, // biXPelsPerMeter;
0, // biYPelsPerMeter;
0, // biClrUsed;
0 // biClrImportant;
};
VOID * pbits32;
HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0);
if (hbm32)
{
HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);
// 创建DC,放位图到它里面
HDC hDC = CreateCompatibleDC(hMemDC);
if (hDC)
{
// 获取每行多少位
BITMAP bm32;
GetObject(hbm32, sizeof(bm32), &bm32);
while (bm32.bmWidthBytes % 4)
bm32.bmWidthBytes++;
// 复制位图到兼容DC中
HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, (HBITMAP)cBitmap );
BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
COLORREF cTolerance = 0x101010;
COLORREF cTransparentColor=::GetPixel(hDC,0,0);
// 为了更好的实现,将使用 ExtCreateRegion() 涵数来创建一区域,这个涵数要用来
// RGNDATA 结构. 我们将用ALLOC_UNI来添加矩形框。
#define ALLOC_UNIT 100
DWORD maxRects = ALLOC_UNIT;
HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
pData->rdh.dwSize = sizeof(RGNDATAHEADER);
pData->rdh.iType = RDH_RECTANGLES;
pData->rdh.nCount = pData->rdh.nRgnSize = 0;
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
// 为了获得透明像素,要分别保留其要透明背景色的最高、最低值
BYTE lr = GetRValue(cTransparentColor);
BYTE lg = GetGValue(cTransparentColor);
BYTE lb = GetBValue(cTransparentColor);
BYTE hr = min(0xff, lr + GetRValue(cTolerance));
BYTE hg = min(0xff, lg + GetGValue(cTolerance));
BYTE hb = min(0xff, lb + GetBValue(cTolerance));
// 从下往上扫描每一个位图(位图是竖直反方向的)
BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;
for (int y = 0; y < bm.bmHeight; y++)
{
// 从左往右扫描每一个像素
for (int x = 0; x < bm.bmWidth; x++)
{
// 连续搜索非透明元素
int x0 = x;
LONG *p = (LONG *)p32 + x;
while (x < bm.bmWidth)
{
BYTE b = GetRValue(*p);
if (b >= lr && b <= hr)
{
b = GetGValue(*p);
if (b >= lg && b <= hg)
{
b = GetBValue(*p);
if (b >= lb && b <= hb)
// 如果是透明元素的话
break;
}
}
p++;
x++;
}
if (x > x0)
{
// 添加像素(x0, y) 到 (x, y+1) ,作为区域中的新矩形
if (pData->rdh.nCount >= maxRects)
{
GlobalUnlock(hData);
maxRects += ALLOC_UNIT;
hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
pData = (RGNDATA *)GlobalLock(hData);
}
RECT *pr = (RECT *)&pData->Buffer;
SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
if (x0 < pData->rdh.rcBound.left)
pData->rdh.rcBound.left = x0;
if (y < pData->rdh.rcBound.top)
pData->rdh.rcBound.top = y;
if (x > pData->rdh.rcBound.right)
pData->rdh.rcBound.right = x;
if (y+1 > pData->rdh.rcBound.bottom)
pData->rdh.rcBound.bottom = y+1;
pData->rdh.nCount++;
// 在Windows98中, 如果矩形数太多的话(ie: > 4000),ExtCreateRegion()涵数可能失败.
// 因此,我们必须通过多步来创建矩形。
if (pData->rdh.nCount == 2000)
{
HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else
hRgn = h;
pData->rdh.nCount = 0;
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
}
}
}
// 到下一行(注意: 位图是竖直反方向的)
p32 -= bm32.bmWidthBytes;
}
// 根据保留的矩形来创建或廷伸区域
HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else
hRgn = h;
// 释放
GlobalFree(hData);
SelectObject(hDC, holdBmp);
DeleteDC(hDC);
}
DeleteObject(SelectObject(hMemDC, holdBmp));
}
DeleteDC(hMemDC);
}
SetWindowRgn(hRgn, TRUE);
MoveWindow(rcNewWnd);
}
// ---------------------------------------------------------
// 名称: GetTrayWndRect
// 功能: 获取系统区范围大小
// 变量: 无
// 返回: CRect -- 系统区大小
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
CRect CAdvertise::GetTrayWndRect()
{
// 查找并返回任务栏窗口大小
CRect rect(0,0,0,0);
CWnd* pWnd = FindWindow("Shell_TrayWnd", NULL);
if (pWnd)
{
pWnd->GetWindowRect(&rect);
}
return rect;
}
// ---------------------------------------------------------
// 名称: OnEraseBkgnd
// 功能: 刷新窗体背景位图
// 变量: 无
// 返回: TRUE --成功,FALSE -- 失败
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
BOOL CAdvertise::OnEraseBkgnd(CDC* pDC)
{
CDC memDC;
CBitmap cBitmap;
cBitmap.LoadBitmap(IDB_ADVERTISE);
memDC.CreateCompatibleDC (pDC);
CBitmap *oldBitmap=memDC.SelectObject(&cBitmap);
pDC->BitBlt (0,0,BACKWIDTH,BACKHEIGHT,&memDC,0,0,SRCCOPY);
memDC.SelectObject(oldBitmap);
return TRUE;
}
// ---------------------------------------------------------
// 名称: OnLButtonDown
// 功能: 左键按下时,打开相应网页
// 变量: 无
// 返回: 无
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
void CAdvertise::OnLButtonDown(UINT nFlags, CPoint point)
{
CRect rcWnd;
GetWindowRect(&rcWnd);
CPoint pt;
GetCursorPos(&pt);
CString url = _T("http://www.philips120dreams.com");
if(rcWnd.PtInRect(pt))
{
HINSTANCE result=ShellExecute(NULL, _T("open"), url, NULL,NULL, SW_SHOW);
}
}
// ---------------------------------------------------------
// 名称: OnMouseMove
// 功能: 鼠标在窗体上移动时,显示手形光标
// 变量: 无
// 返回: 无
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
void CAdvertise::OnMouseMove(UINT nFlags, CPoint point)
{
CRect rcWnd;
GetWindowRect(&rcWnd);
CPoint pt;
GetCursorPos(&pt);
if(rcWnd.PtInRect(pt))
{
if(m_Cursor)
SetCursor(m_Cursor);
}
}