博瑞博客

青春是一个充满活力的季节,即便是我们失去了天使的翅膀,只要我们还有一颗青春的心,那么我们的生活依然能够如阳光般灿烂!......
推荐阅读站长精心推荐阅读
现在位置:首页 > C/C++
  • MFC 窗口显示 任务栏不显示

    MFC 窗口显示 任务栏不显示

    C/C++  10-8  960浏览  0评论  

    ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW,1);//任务栏隐藏

  • UpdateLayeredWindow与SetLayeredWindowAttributes

    UpdateLayeredWindow与SetLayeredWindowAttributes

    C/C++  10-7  1089浏览  0评论  

    首先使用透明之前必须设置该窗口为层级窗口,即增加窗口的扩展风格WS_EX_LAYERED,增加的时候最好使用GetWindowlong获取Ex风格,然后加入后在SetWindowLong设置,最好不适用ModifyStyle增加(有时候不好使,我用vs10可以,但08却不行)。    UpdateLayeredWindow使用之后不会再发出WM_PAINT绘制消息,所有的绘制消息都由UpdateLayeredWindow代而处理,所以不要再OnPaint里做任何事,因为是徒劳的(可能在调用Update..之前有用)。   UpdateLayeredWindow是用兼容的dc去更新当前窗口的dc,所有必须要在兼容的dc上绘制好后去更新当前窗口,故而所有操作应该绘制到兼容的dc上,然后用兼容dc去调用UpdateLayeredWindow去透明更新。    UpdateLayeredWindow最后的参数表明透明的方式,第一种是ULW_ALPHA说明是使用图片本身的Alpha通道去透明(鼠标穿透)当前窗口(如果是最新的bmp格式,支持alpha通道,但必须是32四子节的,否则为3字节即24bit,如果使用4字节,最后字节为alpha通道,该通道决定透明度,如果非得填写24bit即3字节,那么默认的一个alpha通道0,也就是说透明度为0是看不见的,切记!!),如果是这样那么BLENDFUNCTION中的SourceConstantAlpha“源常量透明alpha”是没有用的,如果是用ULW_COLORKEY则说明用颜色掩码去透明窗口,也就是说兼容dc中所绘制的画布中如果颜色与掩码色相同则把这部分透明掉(要在兼容dc中绘制透明色);(SourceConstantAlpha不为0则用该值去透明);   SetLayeredWindowAttributes相当于UpdateLayeredWindow的第二种方法及ULW_COLORKEY,SetLayeredWindow不会导致WM_PAINT不发出,也就是可以在OnPaint中绘制你的东西,但是绘制的颜色如果和SetLayeredWindow中指定的一致则透明掉,否则不透明,另外SetLayeredWindow中透明的地方是可以放置其他组建的!!而UpdateLayeredWindow则不可以(鼠标穿透)。   SetLayeredWindowAttributes经测试必须是非child窗口(Overlapend或PoupUp),否则设置无效!!    在6.0上SetLayeredWindowAttributes使用掩码色的时候也就是第二个参数为掩码色,最后参数为LWA_COLORKEY的时候,只要覆盖控件颜色即可,我使用OnctrlColor返回掩码色画刷,可以将整个窗口置为透明,然后再OnPaint里面绘制非掩码色的图形,即可达到只显示绘制部分图形目的,但是,在VS08中使用alpa透明度透明整个窗口可以达到目的,而使用掩码色的时候无论在OnctrlColor返回何种掩码色,参数中设置该掩码色都是透明的(这点在08中为什么不可用还没搞明白),但是如果去掉OnPaint消息函数却可以达到掩码色透明的作用(或者OnPaint中必须调用父类的OnPaint,否则不起作用!)。   SetLayeredWindowAttributes和UpdateLayeredWindow都可以使得透明区域鼠标穿透,但是实际测试的时候vc6.0上SetLayeredWindowAttributes有时候可以有时候不可以(与鼠标移动快慢有关)。   很重要的一个问题就是vc6.0和vs2008中函数指定的调用约定不一致,vc6.0默认是_stdcall 和vs中函数则不是,所以如果在vs中申明User32.dll中的函数的时候必须手动指定调用约定为WINAPI 或CALLBACK或__stdcall类型,否则在GetProcAddr的时候返回类型不一致,在调用UpdateLayeredWindow或SetLayeredWindowAttributes的时候会出现堆栈被破坏错误!!:Run-Time Check Failure ...     UpdateLayeredWindow与SetLayeredWindowAttributes的另一区别是:UpdateLayeredWindow上所有的东西(包括子控件都必须自己绘制上去,自己响应事件)都由个人处理;SetLayeredWindowAttributes则仅仅处理该窗口的掩码色处理成透明色或将整个窗口的透明度设置为LWA_ALPHA 指定的不透明度值,不影响其他子控件的处理;     以下为updatelayeredwindow使用实例:   void CDlgVideoCompressPage::DrawUI(void) {     if(NULL == m_hWnd)return ;     CRect rtClient;GetClientRect(&rtClient);     HDC hDC = ::GetDC(m_hWnd);     HDC hMemDC = ::CreateCompatibleDC(hDC);     BITMAPINFO bitmapinfo;     bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);     bitmapinfo.bmiHeader.biBitCount = 32;     bitmapinfo.bmiHeader.biHeight = rtClient.Height();     bitmapinfo.bmiHeader.biWidth = rtClient.Width();     bitmapinfo.bmiHeader.biPlanes = 1;     bitmapinfo.bmiHeader.biCompression = BI_RGB;     bitmapinfo.bmiHeader.biXPelsPerMeter = 0;     bitmapinfo.bmiHeader.biYPelsPerMeter = 0;     bitmapinfo.bmiHeader.biClrUsed = 0;     bitmapinfo.bmiHeader.biClrImportant = 0;     bitmapinfo.bmiHeader.biSizeImage = bitmapinfo.bmiHeader.biWidth *                                        bitmapinfo.bmiHeader.biHeight *                                        bitmapinfo.bmiHeader.biBitCount / 8;     HBITMAP hBitmap = ::CreateDIBSection (hMemDC, &bitmapinfo, 0, NULL, 0, 0);     HBITMAP hOldBitmap = (HBITMAP)::SelectObject (hMemDC, hBitmap);     // draw imageCImage img;     if (SUCCEEDED(img.Load(m_strBkImage))){         CRect rtClient;GetClientRect(&rtClient);         img.Draw(hMemDC, rtClient.left, rtClient.top, rtClient.Width(),                  rtClient.Height(), 0, 0, img.GetWidth(), img.GetHeight());         img.Destroy();     }     CPoint DestPt(0,0);     CSize psize(rtClient.Width(), rtClient.Height());     BLENDFUNCTION blendFunc32bpp;     blendFunc32bpp.AlphaFormat = AC_SRC_ALPHA;     blendFunc32bpp.BlendFlags = 0;     blendFunc32bpp.BlendOp = AC_SRC_OVER;     blendFunc32bpp.SourceConstantAlpha = 255;     ::UpdateLayeredWindow(m_hWnd, hDC, NULL, &psize, hMemDC, &DestPt,0,                             &blendFunc32bpp, ULW_ALPHA);     ::SelectObject (hMemDC,hOldBitmap);     ::DeleteObject(hBitmap);     ::DeleteDC(hMemDC);     ::ReleaseDC(m_hWnd,hDC); }          

  • ReadProcessMemory

    ReadProcessMemory

    C/C++  8-8  953浏览  0评论  

    ReadProcessMemory归属为为编程中的内存操作函数, 其作用为根据进程句柄读入该进程的某个内存空间; 函数原型为BOOL ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead); 由布尔声明可以看出, 当函数读取成功时返回1, 失败则返回0, 具体参数含义将在下文中指出。

  • GetWindowThreadProcessId

    GetWindowThreadProcessId

    C/C++  8-8  1069浏览  0评论  

    GetWindowThreadProcessId,找出某个窗口的创建者(线程或进程),返回创建者的标志符。

  • OpenProcess

    OpenProcess

    C/C++  8-8  980浏览  0评论  

    方法名称:OpenProcess 位置:Kernel32.dll OpenProcess 函数用来打开一个已存在的进程对象,并返回进程的句柄。 1.函数原型 HANDLE OpenProcess( DWORD dwDesiredAccess, //渴望得到的访问权限(标志) BOOL bInheritHandle, // 是否继承句柄 DWORD dwProcessId// 进程标示符 );

  • C++中的类模板详解及示例

    C++中的类模板详解及示例

    C/C++  4-12  839浏览  0评论  

    我们在定义函数时,可以通过定义函数模板,来简化一些功能相同而数据类型不同的函数的定义和调用过程

  • 如何正确创建DLL和使用DLL

    如何正确创建DLL和使用DLL

    C/C++  4-11  774浏览  0评论  

    本文将通过一个简单的实例来说明,如何正确的导出DLL中的类、对象、函数,并如何通过静态加载或动态加载的方式来使用DLL。   一、DLL中导出类、函数、对象   1. 创建一个空的Win32 Dynamic-Link Library项目Test   2. 在项目中添加一个Test.h头文件,该文件的内容如下:   //导出类   class __declspec(dllexport) CTest   {   ...   };   //导出函数   __declspec(dllexport) void FuncTest();   //导出对象   extern __declspec(dllexport) CTest  ObjTest;   这段代码中通过__declspec(dllexport)导出了类CTest、函数FuncTest和对象ObjTest。在.cpp文件中实现上面的声明与类的定义后,经编译就可以生成一个.dll和.lib文件了。   二、静态加载DLL   1. 新建一个Win32 项目。   2. 将上面编译生成的.lib文件复制到,该项目下。   3. 在项目中添加一个Test.h(通过该文件实现对DLL的静态加载),该.h文件的内容主要是从DLL的.h文件中复制过来。具体内容如下:   #pragma comment(lib, "test.lib")   //导入类   class __declspec(dllimport) CTest   ...{   ...   };   //导入函数   __declspec(dllimport) void FuncTest();   //导入对象   extern __declspec(dllimport) CTest  ObjTest;   这个.h文件与dll的.h的不同就是,在开头加了#pragma comment(lib, "test.lib"),以及类、函数、对象前面的__declspec(dllexport)变成了__declspec(dllimport) 。通过这些修改就可以告诉编译器,这个.h文件中定义的类、声明的函数和对象 都是从test.dll中导入的。在项目中完成对这些类、函数、对象的调用代码后,就可以将其编译成可执行文件。将生成的可执行为文件、以及上面生成的.dll文件复制到同一个文件夹中就可以正常运行这个可执行文件。   三、动态加载DLL   如果上面的DLL需要被动态调用,这需在DLL的代码中添加一个 .def文件,在该文件中指出哪些被导出的函数和对象是可以动态调用的。根据上面的例子.def文件的内容如下:   LIBRARY    TestImp   EXPORTS   ObjTest   FuncTest   在完成.def文件后,重新编译dll。重新编译dll后就可以对该Dll进行动态调用了,调用过程的代码如下:   typedef void (*HFUNC)()   HINSTANCE hDLL = LoadLibrary("Test.dll");             //加载DLL   if(hDLL)   {   HFUNC hFun = (HFUNC)GetProcAddress(hDLL, "FuncTest");       //获得Dll中FuncTest函数的指针。   if (hFun)   hFun();    //执行函数FuncTest   else   ...            //没有找到函数FuncTest   }   else   {   //加载失败   }   上面的代码实现的对DLL中函数的动态调用,在代码中通过LoadLibrary将DLL加载到内存中,然后GetProcAddress获得指定函数所在的内存地址(即该函数的函数指针),获得指向这个函数的指针后就可以对它进行调用了。   对于DLL中对象的动态调用过程基本上是一样的,先将DLL加载到内存,然后通过GetProcAddress获得对象所在的地址。   从上面可以看出,DLL的动态调用过程就是将DLL加载到内存,然后通过GetProcAddress获得DLL中指定对象或函数在该内存中的地 址,通过该地址就可以对函数或对象进行调用。由于在C++中没有类的对象,也没有类指针一说,所以是无法动态使用DLL中的类的(如果谁知道如何使用可以 告诉我)。

  • duilib DirectUI库里面的一个简单的例子RichListDemo

    duilib DirectUI库里面的一个简单的例子RichListDemo

    C/C++  4-7  964浏览  0评论  

    1、首先来看这里的CRichListWnd 已经不再是从CWindowWnd继承了 classCRichListWnd:publicWindowImplBase 从WindowImplBase中,可以看到有三个抽象函数: virtualCDuiStringGetSkinFolder()=0; virtualCDuiStringGetSkinFile()=0; virtualLPCTSTRGetWindowClassName(void)const=0; 这些都很简单,只是返回固定的string   2、看看WindowImplBase class UILIB_API WindowImplBase : public CWindowWnd , public CNotifyPump , public INotifyUI , public IMessageFilterUI , public IDialogBuilderCallback { …… } 这个类其实也是实现了CWindowWnd、INotifyUI,即一个窗体和消息,所以他含有virtualvoidNotify(TNotifyUI&msg); 但是这里又继承了CNotifyPump,所以这里的Notify可以这么实现:   void WindowImplBase::Notify(TNotifyUI& msg) { return CNotifyPump::NotifyPump(msg); } NotifyPump主要是遍历所有的虚拟窗口把消息传递出去 下面的代码列出了CRichListWnd比较重要的函数:   class CRichListWnd : public WindowImplBase { public: virtual void OnFinalMessage( HWND ); virtual void Notify( TNotifyUI &msg ); virtual LRESULT OnMouseWheel( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); virtual LRESULT OnSysCommand( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); virtual void InitWindow(); virtual LRESULT OnMouseHover( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); virtual LRESULT OnChar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); DUI_DECLARE_MESSAGE_MAP() virtual void OnClick(TNotifyUI& msg); virtual void OnSelectChanged( TNotifyUI &msg ); virtual void OnItemClick( TNotifyUI &msg ); }; 因为WindowImplBase类实现了CWindowWnd中的HandleMessage,所以我们如果需要把一些重要的消息事件给重写就行; 可以看到WindowImplBase中的OnCreate(): LRESULT WindowImplBase::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { …… InitWindow(); return 0; } 所以我们需要把InitWindow给重写了 在InitWindow给每一个控件和XML的控件属性对应起来: // 初始化的事件 void CRichListWnd::InitWindow() { m_pCloseBtn = static_cast<CButtonUI*>(m_PaintManager.FindControl(_T("closebtn"))); m_pMaxBtn = static_cast<CButtonUI*>(m_PaintManager.FindControl(_T("maxbtn"))); m_pRestoreBtn = static_cast<CButtonUI*>(m_PaintManager.FindControl(_T("restorebtn"))); m_pMinBtn = static_cast<CButtonUI*>(m_PaintManager.FindControl(_T("minbtn"))); } 这就完成了初始化,窗口也就起来了 这个Demo中,是使用到了虚拟页的,也就是CPage1,如果不使用,他的消息会回到CRichListWnd中被处理,但是如果CPage1中处理了消息,CRichListWnd就不做处理了 我们来看看CPage1所要处理的消息:   同样的CRichListWnd消息   当页面发生OnClick或者OnItemClick时候,已经挂上了虚拟页CPage1,那么CRichListWnd消息的就失效了 3、关于虚拟页CPage的 这样挂上虚拟页的: CRichListWnd::CRichListWnd(void) { m_Page1.SetPaintMagager(&m_PaintManager); AddVirtualWnd(_T("page1"),&m_Page1); } CRichListWnd::~CRichListWnd(void) { RemoveVirtualWnd(_T("page1")); } 看到这里有个宏(因为继承了CNotifyPump都可以这样用): DUI_BEGIN_MESSAGE_MAP(CPage1, CNotifyPump) DUI_ON_MSGTYPE(DUI_MSGTYPE_CLICK, OnClick) DUI_ON_MSGTYPE(DUI_MSGTYPE_SELECTCHANGED, OnSelectChanged) DUI_ON_MSGTYPE(DUI_MSGTYPE_ITEMCLICK, OnItemClick) DUI_END_MESSAGE_MAP() 这是整个消息映射的,表面我们关心这几个消息函数,同样的还可以在UIDefine.h中找到其他的消息类型的事件 在void CPage1::OnItemClick( TNotifyUI &msg )中原来是没有代码的,需要手动把CRichListWnd的那部分粘上去(或者去掉挂上虚拟页的部分)   之后我们点击进度条的时候,这个函数才会执行   同样的把鼠标停留 在操作按钮上面会执行函数CRichListWnd::OnMouseHover   同样的这个demo的其他部分也就这么回事了                                              

  • DuiLib : 使用CListUI显示海量数据

    DuiLib : 使用CListUI显示海量数据

    C/C++  3-31  2246浏览  0评论  

    最近遇到要在一个DuiLib::CListUI中显示动态数据的子任务. 在使用我改版的DuiLib中发现如下问题, 真杯具. * 如果反复添加删除CListContainerElementUI, 会引起CListUI所在的Dialog退出时挂掉的问题.  e.g. 在CListUI中增加2000条数据, 在CListUI中删掉2000条数据, 如此反复20次.  再退出该CListUI所在的Dialog, UI就挂掉了. 现象是WM_PAINT陷入了一个循环(这个正常), 但是UI显示不出来了.  这个问题我回避了, 搞不定.  采用妥协的方法, 使CListUI只固定一个行数(e.g. 20行),  根据要显示的内容计算List的UI可见部分应该写什么数据.  这样, 只在建立ListUI时, 插入了新的行. 以后都是更新行上的内容. 就不存在退出时UI挂掉的问题. * 当CListUI一次添加太多数据时(e.g. 一次添加2000行), 当滚动时, List反应特别的迟钝, 有时还会导致UI卡死.  这个问题我同样回避了, 搞不定.  采用妥协的方法, 使CListUI只固定一个行数(e.g. 20行),  根据要显示的内容计算List的UI可见部分应该写什么数据.  这样, 只在建立ListUI时, 插入了新的行. 以后都是更新行上的内容. 就不存在滚动List自带竖向滚动条时, 引起的机率性UI卡死. 这个问题让我做了5天实验, 才想到折中的解决方法. 我采用的方法是: * 隐藏CListUI实例自带的竖向滚动条控件, 每次只显示一页的数据 * 在CListUI实例右边的Container中自己摆一个 CScrollBarUI, 用户点击滚动条时, 记录点击的位置, 发送自定义消息, 去刷新CListUI中的显示. 实验过了, 准备20W条数据, 在CListUI中显示, 也是蛮快的, 和数据多少无关, 花费的操作和显示时间都是常量. 这个折中的方法, 让我感到很欣慰. 备注: 数据的容器使用std::vector, 而不能是std::deque, 防止数据释放时, 时间太长. 20W条数据时, std::deque释放的不是一般的慢, 和构造数据的速度比较, 慢了100倍. 使用std::vector时, 构造数据和释放数据的时间是基本相同的. 在20W条数据的条件下做过实验了. 运行效果图:      

  • 动态加载CListUI

    动态加载CListUI

    C/C++  3-31  1327浏览  0评论  

      CListUI* pList = new CListUI; pList->SetTextCallback(this); CListHeaderUI* pHeader = pList->GetHeader(); CListHeaderItemUI* pHeaderItem = new CListHeaderItemUI; pHeaderItem->SetText(L"kdsjlakjfsdl"); pHeaderItem->SetBkColor(0xFFFFFFFF); pHeader->Add(pHeaderItem); pHeader->SetVisible(false); pList->SetFixedHeight(300); pList->SetAttribute(_T("vscrollbar"), _T("true")); pHorzLayout = new CHorizontalLayoutUI; pHorzLayout->Add(pList); pVertLayout->Add(pHorzLayout); //pHorzLayout->SetBkImage(strImage); //pHorzLayout->SetBkColor(0x00ff00); pList->SetBkImage(strImage); CLabelUI* pLabel; for (int i = 0; i < 100; ++i) { CListTextElementUI* pListElement = new CListTextElementUI; pList->Add(pListElement); }