随记~小结

现在换肤已经告一段落, 总结下中间碰到的问题和解决方法。

 

1. 关于动态添加菜单

 

动态添加菜单的方法有很多, 我使用MENUITEMINFO结构实现。代码如下:

 

CMenu* menuappend = new CMenu;

menuappend->CreateMenu();

menuappend->AppendMenu(MF_ENABLED | MF_STRING, ID_SKIN_FIRST, ResStr(IDS_MENU_ITEM_SKIN_DEFAULT));

 

MENUITEMINFO mii;

mii.fMask = MIIM_STATE|MIIM_SUBMENU;

mii.fType = MF_POPUP;

mii.hSubMenu = menuappend;

mii.fState = MF_ENABLED;

 

pPopupMenu->SetMenuItemInfo(i, &mii, TRUE); // pPopupMenu为主菜单

 

 

2. 关于载入位图

 

winapi有两个简单函数可以实现。 LoadBitmap 和 LoadImage, LoadBitmap只能从资源文件读取,LoadImage更可以实现硬盘读取。 

 

HANDLE LoadImage(HINSTANCE hinst,LPCTSTR lpszName,UINT uType,int cxDesired,int CyDesired,UINT fuLoad);

 

参数设置如下:

 

hinst 0为当前模块, 也可用 GetModuleHandle(LPCTSTR lpModuleName) 获得特定模块句柄。

 

lpszName 位图路径,这里要注意的是,这个路径是对应模块路径的相对路径。

 

uType 位图设置为 IMAGE_BITMAP。

 

cxDesired, cyDesired 设为0即可。

 

fuLoad 设置为 LR_DEFAULTCOLOR | LR_LOADFROMFILE, 使函数从硬盘文件读取。

 

WTL中加入一个名为CImage的类,可直接使用该类成员函数Load(LPCTSTR pszFileName) 直接实现, pszFileName为绝对路径。

 

位图使用完后,不要忘记调用DeleteObject()删除。

 

 

3. 关于贴图

 

贴图采用的是双缓冲技巧。 代码如下:

 

CDC dcBmp;

dcbmp.CreateCompatibleDC(&hdc); //hdc为目标设备环境

HBITMAP bmold = (HBITMAP)dcBmp.SelectObject(bmnew); //bmnew为CBitap类对象,SelectObject()返回类型为HWND,需转换为HBITMAP。

BITMAP bm;

bmnew.GetBitmap(&bm);

hdc.SetStretchMode(HALFTONE);

hdc.SetBrushOrg(0, 0); //设置模式为HALFTONE后,必须调用SetBrushOrg();

hdc.StretchBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcBmp, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);

dcBmp.SelectObject(bmold);

bmnew.DeleteObject();

 

出于用户可能会有误删文件的情况, 建议将bmnew保存为全局变量,退出程序前删除。

 

4. 关于对话框

 

WTL和MFC都可以在类内部直接实例化资源文件中的对话框资源。不过有少许区别,如下:

 

使用WTL的话,可以直接继承父类,并在emun中初始化。代码为:

 

class SkinPreviewDlg : public CDialogImpl<SkinPreviewDlg>,

  public WTL::CWinDataExchange<SkinPreviewDlg>

{

public:

  SkinPreviewDlg(void);

  ~SkinPreviewDlg(void);

 

  enum { IDD = IDD_SKIN_PREVIEW }; 

}

 

这样,SkinPreviewDlg类对象就可以直接关联到资源文件。

 

如果使用MFC,则要多家一步。

 

class SkinPreviewDlg : public CDialog

{

  SkinPreviewDlg(void);

  ~SkinPreviewDlg(void);

 

  enum { IDD = IDD_SKIN_PREVIEW }; 

}

 

SkinPreviewDlg::SkinPreviewDlg():CDialog(IDD_SKIN_PREVIEW)

{

}

 

或者调用 CDialog::Create(IDD_SKIN_PREVIEW)。

 

 

如果要创建一个不包含内容的对话框,如CDHtmlDialog, 对话框为一个网页。可以调用CreateIndirect()函数创建。代码如下:

 

DLGTEMPLATE* dialogTemplate;

dialogTemplate = malloc(1, sizeof(DLGTEMPLATE) + sizeof(DLGTEMPLATE));

if (dialogTemplate)

{

  dialogTemplate->style = DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_DISABLED | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU;

  dialogTemplate->dwExtendedStyle = WS_EX_NOACTIVE;

  dialogTemplate->cdit = 0;

  dialogTemplate->cx = 237;

  dialogTemplate->cy = 178;

  if (0 == skindown.CreateIndirect(dialogTemplate, NULL))

  {

    free(dialogTemplate);

    dialogTemplate = NULL;

  }

  skindown.Navigate("http://www.google.com");

}

 

 

5. 关于syslink控件

 

syslink控件不同于statice控件,有两个地方需要注意。

 

1. syslink的字符串格式为"<A HREF=/"http://www.google.com//">谷歌</A>", “http://www.google.com/”为超连接的实际地址,“谷歌”是控件上写的字符串。

 

2. 当点击syslink控件时会发送WM_NOTIFY消息。在WTL中处理如下:

 

BEGIN_MSG_MAP_EX(SkinPreview)

  NOTIFY_HANDLE(IDD_SKIN_SYSLINK, NM_CLICK, OnClickSyslink)

END_MSG_MAP()

 

LRESULT OnClickSyslink(int wParam, LPNMHDR lParam, BOOL& bHandled)

{

  PNMLINK pnmLink = (PNMLINK)lParam;

  ::ShellExecute(NULL, _T("OPEN"), pnmLink->item.szUrl, NULL, NULL, SW_SHOWNORMAL);

  return 0;

}

 

 

6. 关于CDHtmlDialog

 

CDHtmlDialog可以实现对话框与网页的交互,让我们可以像截获WINDOWS消息一样,截获网页消息。头文件为"afxdhtml.h"。

 

可以通过BEGIN_EVENTSINK_MAP 和 END_EVENTSINK_MAP 宏截获网页消息。代码如下:

 

BEGIN_EVENTSINK_MAP(SkinDownload, CDHtmlDialog)

  ONEVENT(SkinDownload, AFX_IDC_BROWSER, DISPID_BEFORNAVIGATE2, OnBeforeNavigate2,   //DISPID_BEFORNAVIGATE2在<exdispid.h>中定义

          VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)

END_EVENTSINK_MAP()

 

void BeforeNavigate2(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName,

                     VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel)

{

  std::wstring url = VBSTR(URL);

  if (url.find(L"zip") != std::wstring::npos)

  {

    DownLoadSkin(url);

    *Cancel = TRUE;

  }

 

}

 

正常情况下,当点击一个链接以后,会跳转到该页面,将*Cancel设置为TURE,可以拦截跳转。

 

 

7. 关于下载文件

 

首先要包含头文件“afxinet.h”。代码如下:

 

HINTERNET hi = InternetOpen(L"http_down_dll", INTERNET_OPEN_TYPE_PRECONFIG, NULL, INTERNET_INVALID_PORT_NUMBER, 0);

if (hi == NULL)

  return;

HINTERNET hUrl = InternetOpenUrl(hi, url, NULL, 0, INTERNET_FLAG_RELOAD, 0);

if (hUrl == NULL)

{

  InternetCloseHandle(hi);

  return;

}

DWORD optbuf[256];

DWORD optlen = 256;

if (HttpQueryInfo(hUrl, HTTP_QUERY_CONTENT_LENGTH, optbuf, &optlen, NULL) == FALSE)

{

 

  InternetCloseHandle(hUrl);

  InternetCloseHandle(hi);

  return;

}

char tmpbuff[256];

sprintf(tmpbuff, "%s", optbuf);

long flen = atol(tmpbuff);

if (flen <= 0)

{

  InternetCloseHandle(hUrl);

  InternetCloseHandle(hi);

  return;

}

HANDLE hfile = CReateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

if (hfile == INVALID_HANDLE_VALUE)

{

 InternetCloseHandle(hUrl);

 InternetCloseHandle(hi);

 return;

}

BYTE bufferstr[1024];

DWORD len = 0; wlen = 0;

DWORD wsum = 0;

long sendlen = flen;

 

while (InternetReadFile(hUrl, (LPVOID)bufferstr, 1024, &len)&&len != 0)

  WriteFile(hFile, bufferstr, len, &wlen, NULL);

 

CloseHandle(hFile);

InternetCloseHandle(hUrl);

InternetCloseHandle(hi);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值