WinxGui Home

启用WinxGui Wiki

参见:http://wiki.winxgui.cn/

评论

FreeCode For VS60使用说明

欢迎使用 FreeCode for VS60 Add-in

下载地址:FreeCode0.3

版本: 0.3.0501 , –>

评论

COM自动化专题(COM Automation)

评论

内存管理专题(Memory Management)

评论

WINX AppWizard使用指南

winx-1.1.08版本发布了。此次更新的内容较多。您可以到这里了解详情。最引人注目的当然是WINX也提供了Application Wizard了,你可以很方便地开始建立自己的WINX应用程序。以下是WINX AppWizard的一个简单使用指南。  

安装

  1. 下载winx-1.1.08.zip解压到winx-1.1.08目录。
  2. 进入winx-1.1.08\winx目录,你可以发现一个名为install.bat的文件,双击执行它。
  3. 还要下一步吗?没有了。

使用

  1. 打开Visual C++ 6.0,新建一个Project,此事出现以下对话框:
     
     
  2. 请注意新工程的所在的位置(注意上图的”Location:”字样)。WINX的AppWizard假设你的工程和WINX在同一个目录树下。如果不按照这个要求,将出现以下错误对话框:

     
  3. 点下一步,进入这个界面:

     
  4. 后面总体来说比较傻瓜式,就不罗唆了。有一点需要注意:如果你没有下载winsdk.zip,请进入”Advance…”对话框,把其中Enable all features of Windows选项去掉。如图:

     
  5. 上面的Advance对话框中,我的名字和Email请替换为自己的。

意外

如果你下载了winsdk.zip,并且使用了它,有时你可能遇到以下Link错误:uuid.lib文件破坏。

这是我提供的winsdk有些lib文件破坏了,临时的解决方案是,拿VC++ 6.0带的uuid.lib替换掉winsdk/lib/uuid.lib 即可。

评论

如何用WINX实现可滚动的窗口(ScrollWindow)

用Windows SDK实现过可滚动的窗口(ScrollWindow)的读者都知道,实现一个ScrollWindow真不是一件容易的事情。你得响应好多好多的滚动条消息,还要处理鼠标滚轮。现在,你用WINX则只需要3步完成:

  1. 让你的类从ScrollWindow<>继承。
  2. 实现一个名为DoPaint的函数。其原型为:void DoPaint(winx::DCHandle dc); 这个函数功能是绘制整个视图,包括那些滚出屏幕之外的区域。其实实际上你应该把DoPaint理解为在以一个虚拟的不带滚动条的视图(View)中绘制。
  3. 告诉WINX你的虚拟视图(View)有多大。这可以通过SetScrollSize函数完成。

至此,一切搞定。我们看一个最简单的例子:

#include <winx/ScrollWindow.h>
#include 
resource.h

// ————————————————————————-
// class CMyView

class CMyView : public winx::ScrollWindow<CMyView>
{
    WINX_CLASS(
MyView);

public:
    LRESULT OnCreate(HWND hWnd, LPCREATESTRUCT lpCS)
    {
        SetScrollSize(
800800);
        
return 0;
    }

    void DoPaint(winx::DCHandle dc)
    {
        dc.TextOut(
11, _T(Hello, WINX!));
        dc.TextOut(
1300, _T(You are welcome!));
    }
};

// ————————————————————————-
// CHelloDlg

class CHelloDlg : public winx::ModalDialog<CHelloDlg, IDD_HELLO>
{
};

// ————————————————————————-

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     
int       nCmdShow)
{
    CMyView::RegisterClass();
    CHelloDlg dlg;
    dlg.DoModal();
    return 0;
}

这里我不再解释整个程序的流程。如果你不能理解为什么没有地方去创建CMyView类,建议你去看看前面WINX相关的文章。例如:

这里我们关注CMyView类。当然,这个例子有过于简单,虚拟的视图(View)大小始终为800×800,不太符合实际的情况。复杂一点的,我们这里就不贴代码了,请参考WINX带的例子。关于ScrollWindow相关的,我们提供了4个:

  • ScrollWindow(Basic)     tutorials/winx/step019-scroll-window/1.basic
  • 一个简单的图象浏览器     tutorials/winx/step019-scroll-window/2.imageview (*)
  • FormView(支持滚动的对话框)   tutorials/winx/step019-scroll-window/3.formview
  • ZoomView(ZoomScrollWindow)   tutorials/winx/step019-scroll-window/4.zoomview

注:由于带(*)项目使用了Gdiplus,如果你使用VC++6.0,需要更新到最新的winsdk。

特别推荐上面的简单图像浏览器。代码才100多行,功能可不弱哦。另外,FormView在MFC中叫CFormView,WINX我们叫FormWindow(这个类WTL中没有对应的)。

下载:

评论

从VC++到GCC移植:谈两者的语法差异

类型引用

template <class T>
class  Foo
{
    typedef T::SomeType SomeType;
};

这段代码在VC++中一点问题也没有,但是GCC并不允许,因为它不知道T::SomeType是什么。你需要改为:

template <class T>
class  Foo
{
    typedef typename T::SomeType SomeType;
};

通过typename T::SomeType告诉GCC,SomeType是一个类型名,而不是其他东西。

当然,这种情况不只是出现在typedef中。例如:

template <class Container>
void visit(const Container& cont)
{
    
for (Container::const_iterator it = cont.begin(); it != cont.end(); ++it)
         …
}

这里的Container::const_iterator同样需要改为typename Container::const_iterator。

基类成员引用

template <class Base>
class Foo : public Base
{
public:
    
void foo() {
         base_func();
         m_base_member 
= 0;
    }
};

这段代码在VC++中同样没有问题,但是GCC中不能通过。因为GCC并不知道base_func,m_base_member是什么。对于这个问题,你可以有两种改法:

改法1:加上域作用符Base::

template <class Base>
class Foo : public Base
{
public:
    
void foo() {
         Base::base_func();
         Base::m_base_member 
= 0;
    }
};

改法2:使用using指示符

template <class Base>
class Foo : public Base
{
public:
    
using Base::base_func;
    
using Base::m_base_member;

    void foo() {
         base_func();
         m_base_member 
= 0;
    }
};

这两种方法各有好处,在class Foo中出现大量的Base::base_func、m_base_member的引用时,使用using是方便的。而如果只有一次,那么方法1显得简短。

交叉引用许可

class SomeClass;

template <class T>
class Foo
{
public:
     
void foo(SomeClass& a) {
          a.some_func();
     }
 
     void foo2() {
          SomeClass a;
          a.some_func();
     }
};

class SomeClass
{
public:
      
void some_func() {
           …
      }
};

由于VC++对模板函数的迟编译,因此,一个模板类不只是可以调用一个尚未出现的类成员函数(或者访问其成员变量),甚至可以定义其实例。这种语法对C++来说确实显得怪异。因为等到编译后面的SomeClass时,他又可以在其函数中定义class Foo的实例,从而出现交叉引用的情况。这在非模板函数的情形下就算你用VC++亦难以做到。

遇到这种情况,该如何移植到GCC中?这个问题有点棘手。我个人认为出现这种情况是不太应该的,这意味着对类与类之间的关系混淆不清。你需要仔细审视一下这两个类正确的关系是什么。如果是移植库(例如WTL就有多处这样的情形)的过程中遇到这种情况,可以把函数的实现体改为放到类定义体外,如下:  

class SomeClass; 

template <class T>
class Foo
{
public:
     
void foo(SomeClass& a);
     
void foo2();
};

class SomeClass
{
public:
      
void some_func() {
           …
      }
};

template  <class T>
inline 
void Foo<T>::foo(SomeClass& a) {
    a.some_func();
}

template <class T>
inline 
void Foo<T>::foo2() {
    SomeClass a;
    a.some_func();
}

评论

移植MFC程序到WINX

WTL脱离MFC程序员的习惯有点远了。这也是它让初学者畏惧的一个原因。WINX其实是更接近MFC的WTL:它提供了更接近于MFC的使用界面,并努力使得MFC代码可以更加容易地移植到WINX中。关于MFC代码移植,我们已经在WINX中提供了几个样例。有一点你需要理解的是,WINX并不十分关注将一个MFC应用程序移植到WINX下,因为那只有学术价值,但并不具备商业价值,我个人并不推荐你这样做。关于MFC移植,我的侧重点始终在于移植一些具备可重用性较高的MFC代码,例如MFC编写的控件等。这里有我关于WINX定位方面更为详细的讨论。 

所以,有一点你需要明确,本文并不是在推荐你用WINX把你的MFC程序重写一遍。但是这有助于你理解WINX,了解如何从MFC程序员转换为WINX程序员。

WINX对于MFC的策略,是兼容其用户群已经习惯的用法。只要掌握一定的规则,我们可以发现,从MFC到WINX,是如此轻松。 本文就是介绍如何从MFC到WINX的一个指南。由于WINX目前主要关注对话框应用程序,故此,这一篇MFC程序移植指南,主要针对的是基于对话框的MFC程序。点击此处阅读全文。

评论 (5)

winx移植手记:支持dev-c++, mingw32

移植winx到gcc编译器,确实比移植到Visual C++ 2003辛苦一些,花了我整整一天时间,还只是移植了winx中的一个子库:stdext(C++标准扩展部分)。感兴趣可到这里下载。因为仍然是windows平台开发,我选择的是Dev-C++, mingw32。之所以是Dev-C++作为开发平台,是依据大家在《WINX调查:您使用什么C++开发平台?》的反馈决定的。

考虑到现在已经比较晚了,我先简单把一些感受比较强烈的东西记一下:

  • 总体说来,对模板编译的支持,gcc比Visual C++系列(包括Visual C++ 2005)好很多。有不少细节上的看起来非常愚蠢的手误,由于代码没有用到,VC++就无法检查出来,用gcc很快就原型毕露了。对于VC++这种不调用就不进行一般性的语法检查的做法,我一直持否定的态度。虽然这可能加快了编译速度,但是对库的提供者无疑是不利的。 
  • gcc对语法的检查比VC++严格,这有利于你编写更符合C++标准的代码。

以上是赞美的话,但是相对来说,问题似乎更多:

  • Microsoft的调试器真的是无可匹敌。用惯了Visual Studio,用gcc/gdb的调试实在痛苦。
    • 我太习惯看函数调用栈了,Dev-C++的调试居然没有函数调用栈,不知道是gdb不支持,还是Dev-C++没有做。
    • 当我要看一个结构体的内容时,Dev-C++只是打印该结构体的地址,并不显示更详细的信息。例如当你调试到某个类成员函数时,希望看看this对象的总体状态,却苦于没有办法。
  • mingw32似乎没有支持fastcall调用,这是一个莫名奇妙的错误。由于一开始我压根没想到调用方式的问题,耽误了我不少时间。由于winx中所有的函数调用都采用winx_call,它被定义为__fastcall。mingw32并不报告这是一个错误,但是程序的执行却产生了非法操作。尝试去调试函数调用的跳转却非常奇怪,跑到一个根本没有调用过的函数上去了。由于现象奇特,我意识到这可能是由于调用方式引起的,把winx_call定义为cdecl,问题得以解决。
  • 后来我想到gcc中调用方式的写法和VC++不太一样,应该写成:__attribute__ (( fastcall)),但问题依旧。
  • mingw32编译出来的exe有点大(与Visual C++相比)。同样的代码(控制台程序),VC++ 6.0编译是44k,mingw32编译出来是521k(Release版本)。

对于Dev-C++,总体感觉还可以,有以下几点觉得需要改进:

  • Dev-C++的工程文件过于简单,不支持多种配置。
  • 函数跳转。VC++配上Visual Assist,按Alt+G跳转习惯了,没有这个功能还真不习惯。不过这个功能确实不易做。
  • Find in Files功能支持在工程中找,也支持在所有打开的文件中找,唯独少了我觉得最实用的:在一个目录中找。

我用gcc也算有一段日子了,但是Dev-C++是首次使用,有些结论可能是我认识不足所致。把它写出来,也是欢迎有经验的朋友可以指出其中的错误,也欢迎与我交流心得。

 对winx感兴趣?请到这里下载。

评论