TAG / vs/vc++

微软 STL lower_bound() 在 DEBUG 下的诡异编译错误

众所周知,在 STL 中,对于有序的 vector 容器,使用 binary_search、lower_bound/upper_bound 等搜索算法要比直接 find 高效得多。但是由于各个 STL 实现版本没有统一的标准,在 DEBUG 环境下各自的校验机制千差万别,这就导致可能出现一些让人郁闷的情况,比如这次的主角,微软的 STL。

CONTINUE READING »


VS2010 中的 C++ 0x 新特性:Lambdas、auto 和 static_assert

转载自痴痴笑笑的博客,略有删改。

尽管 C++ 社区对 C++ 0x 很是追捧,但是各厂商对于新标准的支持并不热乎。盼星星盼月亮,微软作为 Windows 平台上最强势的 C++ 编译器厂商也终于在 Visual Studio 2010 中开始支持 C++ 0x 的特性。

Visual Studio 2010 中的 Visual C++ 编译器,即 VC10, 包含了 4 个 C++ 0x 的语言特性:lambda 表达式,自动类型推演(auto 关键字),静态断言(static_assert)和右值引用(rvalue reference)。
CONTINUE READING »


让 Visual Studio 2005 自动生成 Manifest

微软同学永远是个把简单问题复杂化的孩子,这不,当年为了在 Windows XP 中同时支持两套控件风格(新的 XP 风格和旧的 95/98 风格),“发明”了 .manifest 这么个玩意,使以前的老程序也能自动使用上新的控件风格。

然而在 VS 里,微软并不是总是默认帮我们自动生成这个破玩意儿。最早的办法就是手写一个 .manifest XML 文件,不过这个办法在 VS 2005 编译出来的程序里似乎并不起作用。当然,新方法总是随之而出的,而且很“简单”(绕了一大圈又回来了):

在 Project Properties 对话框的 Configuration Properties | Linker | Manifest File | Additional Manifest Dependencies 选项里,填入:

"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'"

或者在程序里直接写下如下代码:

#pragma comment(linker, "\"/manifestdependency:type='Win32' name='Test.Research.SampleAssembly' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='0000000000000000' language='*'\"")

太阳又照常东升西落了 :)


Visual Studio 2008 无法进入修复/卸载界面的解决办法

最近需要在家办公,硬盘空间又不够了,只好卸了 VS2008 重装 VS2005,结果无论通过控制面板的卸载还是通过光盘的 autorun.exe,都在检查配置的时候弹出“A problem has been encountered while loading the setup components. Canceling setup.”的错误对话框,然后就自动退出了,连修复的机会都完全不给……

放狗在 MSDN 的论坛里搜到了这篇帖子里 George175 给出的解决办法,原来是 VS2008 的一个 patch 捣的乱,直接进控制面板,进入添加/删除程序(或卸载程序),左边选择查看/卸载更新,找到“Hot Fix for Visual Studio 2008”这个玩意儿,直接咔嚓掉。

然后,VS2008 就能正常卸载了。

另,微软的一位同学说安装 VS2008 SP1 也能解决,没有验证,应该不会有错。


征服 Visual Studio 的 Editor

  • 块选中
  • 类似 UltraEdit 里的“列模式”,按住 Alt 键再移动光标,就可以选择一块范围内的内容,而不必被束缚在只能一行接一行的选中方式了。

  • 整行剪切 / 复制 / 粘贴
  • 平时我都是用鼠标移到一行最左边的行号区去选中一行,然后执行复制或拖动等操作,其实,只要光标在某一行,直接按 Ctrl + X / Ctrl + C,就等于剪切/复制整行了,非常方便。

  • Clipboard Ring
  • 一直以来,当需要在多个文件中复制粘贴多个内容时,我都很笨地挨个 Ctrl + C / Ctrl + V,从来也懒得想是不是该搞个 multi-clipboard 工具来提高效率 -,-|||

    其实,从 VS2003 开始,VS 就已经内置了多重剪贴板的功能,虽然只支持当前 VS 进程内多文件间的复制粘贴,这就是 Clipboard Ring。Clipboard Ring 采用 LIFO(后进先出)的方式组织,即最后被复制或粘贴的内容排在环的最前面,最大支持 10 块剪贴板。用法很简单,对需要复制的多个内容块按 Ctrl + C,然后到需要粘贴的地方按 Ctrl + Shift + V,选择需要粘贴的内容就 Ok 了。每个 VS 版本的 Clipboard Ring 操作略有不同,在此不赘述了。

  • 代码重构
  • 待续……


遍历 CTreeCtrl

CTreeCtrl 的 GetNextItem 成员函数很诡异,nCode 设为 TVGN_NEXT | TVGN_CHILD 会一直返回传进去的 hItem 值,而不是返回下一个兄弟 item “或”第一个 child item。

所以,只好自己写遍历函数,没有采用递归的做法,用了一个 STL List 容器来保存下一个兄弟 item 和第一个 child item,遍历返回的依据是 item 的 lParam 值等于给定的值。

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
HTREEITEM CModelNodeTreePane::_GetTreeItemByID(const unsigned int uiItemID)
{
    HTREEITEM   hCurrItem = m_kModelNodeTreeCtrl.GetRootItem(),
                hItem;
    std::list kItemList;
 
    kItemList.push_back(hCurrItem);
 
    while (kItemList.size() > 0)
    {
        hCurrItem = kItemList.front();
        kItemList.pop_front();
 
        if ((unsigned int)m_kModelNodeTreeCtrl.GetItemData(hCurrItem) == uiItemID)
        {
            return hCurrItem;
        }
 
        if ((hItem = m_kModelNodeTreeCtrl.GetChildItem(hCurrItem)) != NULL)
        {
            kItemList.push_back(hItem);
        }
        if ((hItem = m_kModelNodeTreeCtrl.GetNextSiblingItem(hCurrItem)) != NULL)
        {
            kItemList.push_back(hItem);
        }
    }
 
    return NULL;
}

动态创建的 CTreeCtrl 实例的消息响应

由于程序里的 CTreeCtrl 控件实例是通过 CTreeCtr::Create() 来创建的,无法通过 VS 的 Properties 面板里的 Control Events 工具来生成消息映射函数,但控件又需要响应鼠标点击事件,这时最简单的办法就是重载 CTreeCtr 实例的 owner 的 OnNotify() 成员虚函数(这个 owner 也必然是 CWnd 的子类):

protected:
    virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
BOOL CTreePane::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    NMHDR* pNMHDR = (NMHDR*)lParam;
    ASSERT(pNMHDR != NULL);
 
    switch (pNMHDR->code)
    {
    case TVN_SELCHANGED:
        _OnTreeCtrlSelChanged(wParam, lParam, pResult);
        break;
 
    default:
        break;
    }
 
    return CWnd::OnNotify(wParam, lParam, pResult);
}

IE8 引发 VS 2005/2008 向导出错的解决方案

Internet Explorer 8 正式版会导致  Visual Studio 2005 / 2008 里的部分 VC++ 向导出错,包括:

  • Add Function
  • Add Variable
  • Smart Device – New Project Creation
  • Smart Device – Add Class

VC++ 团队给出了解决方案:

  1. 运行注册表编辑器 regedit(64 位系统请使用 32 位版本
  2. 定位到“HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet
    Settings\Zones
    ”下
  3. 新建一个名为 1000 的项
  4. 在 1000 这个项下,新建一个 DWORD 值,名为 1207,值为 0x000000

然后重启 VS 即可。

注意:VS 2005 必须装上 SP1

想深究这个问题原因,可以参看原文