用Win32 Api编写Win7/XP风格的界面

首先在RES目录下建一个文件,命名 windows.manifest 后缀为:.manifest
然后再用记事本打开放入如下代码:

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity name="Microsoft.Windows.XXXX" processorArchitecture="x86" version="5.1.0.0" type="win32" />
    <description>Windows Shell</description>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*" />
        </dependentAssembly>
    </dependency>
</assembly>

然后导入资源,把文件windows.manifest添加到工程的资源中:
插入->资源->导入->文件类型改为“所有文件”->找到windows.manifest->弹出对话框
资源类型 填”24″->确定后。再把资源的ID改为”IDR_MANIFEST”
然后在String Table中添加IDR_MANIFEST,值为1

重新生成编译运行。

文章是转载过来的,没高清来源!

写在博客空间到期之前

前两天在删除垃圾邮件的时候看到了这个博客的空间提供商发给我的邮件,邮件上说,我的博客到3月30日日就到期了。工作之后一直都没什么时间来打理博客,我只好等到周末晚上抽空把博客搬迁到新的空间去。目前还没有租好空间,如果你认识好的空间提供商,不妨介绍一下吧。

工作上的笔记一般都发到印象笔记中,平时拍的照片也只是发到lofter上去,所以,博客就没怎么更新。我已经来这边工作了一阵子了,感觉能力上进步不是很大。我做需求总是做得很慢,之前是因为写代码的速度太慢了,后来写代码的速度加快了,但是做需求的速度还是那样,原因是我调试代码和自测的时间比以前久了。之所以如此,是因为很容易犯错的我怕犯错,所以我在编写程序的时候不得不反复调试,可是即便如此,我的提测的代码还是偶尔会爆出一些BUG。

我觉得,无论做什么行业“快速提升”自己都是一种能力,注意,这里所说的是“快速”提升,不是“提升”,“快速”才是重点,“提升”只是用来修饰这个“快速”。很显然,我目前很缺乏“快速提升”自己的能力。我最近也在反思我为什么缺乏这种能力,并希望自己今后能在工作和生活的方方面面都有一个提升!加油!

Win32 api使用双缓冲绘图

写下这段代码,用作备忘,其中的CLIENT_WIDTH、RGH_WITHE、RGB_SEAGREEN是我自己定义的宏。

case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            HDC hCompDc = ::CreateCompatibleDC(hdc);
            HBITMAP hBitmap = ::CreateCompatibleBitmap(hdc, CLIENT_WIDTH, CLIENT_HEIGHT);
            SelectObject(hCompDc, hBitmap);

            RECT rect = {0};
            GetClientRect(hWnd, &rect);

            HBRUSH hBkBrush = (HBRUSH)::CreateSolidBrush(RGB_WHITE);
            FillRect(hCompDc, &rect, hBkBrush);

            HPEN hPen = ::CreatePen(PS_SOLID, GRID_LINE_WIDTH, RGB_SEAGREEN);
            SelectObject(hCompDc, hPen);

            PaintMap(hCompDc);

            BitBlt(hdc, 0, 0, CLIENT_WIDTH, CLIENT_HEIGHT, hCompDc, 0, 0, SRCCOPY);

            if (hCompDc)
            {
                DeleteDC(hCompDc);
            }

            if (hBitmap)
            {
                DeleteObject(hBitmap);
            }
            if (hBkBrush)
            {
                DeleteObject(hBkBrush);
            }
            if (hPen)
            {
                DeleteObject(hPen);
            }

            EndPaint(hWnd, &ps);
        }
        break;

SetUnhandledExceptionFilter设置处理异常函数.

SetUnhandleExceptionFilter函数

Windows平台下的C++程序异常通常可分为两种:结构化异常(Structured Exception,可以理解为与操作系统相关的异常)和C++异常。对于结构化异常处理(SEH),可以找到很多资料,在此不细说。对于crash错 误,一般由未被正常捕获的异常引起,Windows操作系统提供了一个API函数可以在程序crash之前有机会处理这些异常,就是 SetUnhandleExceptionFilter函数。(C++也有一个类似函数set_terminate可以处理未被捕获的C++异常。)

SetUnhandleExceptionFilter函数声明如下:

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
    LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
    );
    //其中 LPTOP_LEVEL_EXCEPTION_FILTER 定义如下:

typedef LONG (WINAPI *PTOP_LEVEL_EXCEPTION_FILTER)(
    struct _EXCEPTION_POINTERS *ExceptionInfo
    );

typedef PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER;

简单来说,SetUnhandleExceptionFilter允许我们设置一个自己的函数作为全局SEH过滤函数,当程序crash前会调用我们的函 数进行处理。我们可以利用的是 _EXCEPTION_POINTERS 结构类型的变量ExceptionInfo,它包含了对异常的描述以及发生异常的线程状态,过滤函数可以通过返回不同的值来让系统继续运行或退出应用程 序。
关于 SetUnhandleExceptionFilter 函数的具体用法和示例请参考MSDN。

转载自http://blog.sina.com.cn/s/blog_648d306d0100qmca.html

利用模板实现多态性

今天早上我在看《MFC程序员的WTL指南》,其中开篇就有讲到一个例子,里面有一段这样的代码:

template <class T>
class B1
{
public:
    void SayHi()
    {
        T* pT = static_cast<t*>(this);
        pT->PrintClassName();
    }
protected:
    void PrintClassName() { cout << "This is B1"; }
};

class D1 : public B1<d1>
{
    // No overridden functions at all
};

class D2 : public B1<d2>
{
protected:
    void PrintClassName() { cout << "This is D2"; }
};

在D1中,由于没有重写任何函数,因此当B1中的this指针被转成D1指针的时候,pT->PrintClassName();将调用基类中的PrintClassName();函数,
在D2中,PrintClassName();被重写,因此 pT->PrintClassName();将会调用被重写后的PrintClassName();函数

在类和继承比较多的情况下,这样可以节省不少内存。

【Windows编程基础】设置SeDebugPrivilege提升进程权限

在openprocess的时候,如果需要全部权限,是需要SeDebugPrivilege privilege的。以下我写的代码,以后可能常常用到,这里贴出来,以后直接从这里复制吧!

BOOL EnableDebugPrivilege()
{
    HANDLE              hToken = NULL;
    LUID                Luid = {0};
    TOKEN_PRIVILEGES    tp = {0};

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken))
    {
        return FALSE;
    }
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Luid))
    {
        CloseHandle(hToken);
        return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = Luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL))
    {
        CloseHandle(hToken);
        return FALSE;
    }
    return TRUE;
}

设置进程特权大概就三个步骤:
第一步:查询特权的名字
LUID Luid = {0};
LookupPrivilegeValue(NULL, szPrivName, Luid);

第二部:打开进程令牌
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES|TOKE_QUERY, &hToken);

第三部:调整特权
AdjustTokenPrivileges(hToken…);

VS2005设置程序必须以管理员权限运行

公司目前使用的VS2005作为开发环境。而前不久,我需要编写一个demo,该demo在Vista以上的系统上必须以管理员权限运行。而VS2005是一款比较老的编译器,刚发布那时,Windows还不支持UAC。所以要通过一些设置才能让VS2005编译出来的程序出现“小盾牌”

exe_with_uac

方法如下:
①:在工程的目录下创建一个mani.xml文件,文件内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
      <ms_asmv2:security>
        <ms_asmv3:requestedPrivileges xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
          <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
        </ms_asmv3:requestedPrivileges>
      </ms_asmv2:security>
    </ms_asmv2:trustInfo>
</assembly>

②打开工程的属性(Properties)“Manifest Tools” ==> “Input and Output” ==> “Additional Manifest File” 设置成刚刚创建的xml文件:“./mani.xml”

编译之后就可以看到生成的exe图标下的小盾牌了。

编译的过程中可能会产生一条这样的警告:

.mani.xml : manifest authoring warning 81010002: Unrecognized Element "requestedPrivileges" in namespace "urn:schemas-microsoft-com:asm.v3".

我回来了

开篇又是那句老话:“好久没更新博客了”,确实很久没有发一些有意义的东西了。刚刚大致地翻了一下我以前写过的博客,居然没几篇质量拿得出手的。

来公司实习之后,我就没怎写博客,大多数时间我只是把一些东西从VS里或者浏览器里复制到印象笔记里。博客,似乎被我遗忘了。

我决定以后还是把博客利用起来,多写一些有意义的博客,发出来,接受大家的批评(虽然没有人看)。

Qt限制鼠标移动范围

几个月前,我编写一个截图程序,这个截图程序有涂鸦功能,在我遇到了一个难题,那就是在涂鸦的时候如何才能让光标只在特定的区域内移动?

一开始我的想法是,设置setMouseTracking为true,然后重载

void QWidget::mouseMoveEvent(QMouseEvent * event)

函数,一旦鼠标移出窗口,我就用

 QCursor::setPos (int x, int y)

把它移回来。

这样做,功能是达到了,但是效果不是很好,每次尝试着将鼠标移出区域的时候,鼠标箭头都会在区域的边缘不停地抖动。

最近接触了一些Windows编程,然后发现可以用Windows API来限制鼠标的区域,下面是一段简单的代码:

#include "mainwindow.h"
#include <qapplication>
#include <windows.h>
#include <windef.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    RECT mainWinRect; //RECT在windef.h中被定义
    mainWinRect.left = (LONG)w.geometry().left();
    mainWinRect.right = (LONG)w.geometry().right();
    mainWinRect.top = (LONG)w.geometry().top();
    mainWinRect.bottom = (LONG)w.geometry().bottom();

    ClipCursor(&mainWinRect); //这是Windows API

    return a.exec();
}

这样一来,鼠标就只能在mainWinRect的范围内移动了,你也可以根据自身的需求设定RECT的值。
鼠标是公共的资源,如果你想取消限制,那么可以调用

ClipCursor(NULL)

来释放对鼠标的限制。

另外要注意的是:
①假如你要限制鼠标在xxWidget内,只能等xxWidget实例被构建之后才能限制鼠标范围。
②如果在鼠标受限的时候,用户按下了Windows键,那么当前的窗口失去鼠标,鼠标受限会被取消。

CreateFile打开磁盘驱动器"\.PHYSICALDRIVE0"失败的解决方法

打开磁盘驱动器的代码如下

HANDLE hDevice = CreateFile(
    TEXT("\\.\PHYSICALDRIVE0")
    0,
    FILE_SHARE_READ|FILE_SHARE_WRITE,
    0,
    OPEN_EXISTING,
    0,
    0);

出现错误时,检查这几点:
第一:

路径必须写成
TEXT("\\.\PHYSICALDRIVE0")
而不应该是
TEXT("\.PHYSICALDRIVE0")

第二:OPEN_ALWAYS改成OPEN_EXISTING

我也不知道为什么,虽然从代码语义上来说应该是OPEN_ALWAYS,但是确实要改成OPEN_EXISTING才能成功,我也不知道为什么

第三:在Vista/win7上用管理员权限启动编译好的程序,或者以管理员权限启动VS。