用Eclipse + CDT + MinGW做Windows编程(第三部分)

Posted on 2009-01-12 12:26  Inshion  阅读(3301)  评论(5编辑  收藏  举报

 

第三部分 一个Demo程序及相关说明

3.1 在Eclipse中导入并运行一个C++项目
  点此处可以下载本文中用到的C++项目(Eclipse+CDT项目,环境按第一部分的说明配置),下载后解压。
  然后在Eclipse中使用File->Import->Genaral::Existing Project into Workspace向导即可把下载的项目导入到开发环境中。便会看到如下图的项目:

  如果Build成功,Run起来以后,可以看到如下的运行结果:


  同时控制台给出以下输出:

  Main Program Started!
  Application::SetWinMainArgs(...)
  MyApp::InitInstance() -- start
  Window::Create(...) <--> start
  Application::RegisterWndClass(...) <--> start
  Application::RegisterWndClass(...) <--> end
  Window::Create(...) <--> end
  MyApp::InitInstance() -- end
  Application::Run()

  但是需要注意的是,如果是直接新建一个项目,再编写如此的程序代码,调用WindowsAPI,一般情况下直接编是编不通的,会提示某种错误
  比如:undefined reference to `TextOutA@20'
  或者是:undefined reference to `SetBkColor@8'
  因此要对项目加上一个参数设置。
具体的设置项目如下:
   在项目上点右键,选择“属性”,就会弹出Eclipse的项目设置对话框,在按图所示的地方添加-mwindows参数即可(C/C++Build -> Settings ->MinGW C++ Linker -> Expert settings:)。注意,这些选项页中有很多相似的页面,看清图示的设置框究竟是哪一个(MinGW C++ Linker),不要加错地方了(=0=|||)。

  顺便提一句,随着我们对项目的扩展,可能有越来越多的项目需求,比如引用静态库、引用DLL、使用rc资源等,这些要求都涉及到对项目属性中某些参数的修改。本部分中只涉及-mwindows参数,其它的参数会在后续的部分中分别介绍。
  OK,如果项目运行成功,我们就来分析一下这个项目的结构,看是否和第一部分描述的是同样的组织方式。

3.2 源代码说明
  回顾一下第一部分中提到的Windows应用程序的运行示意图:

   对照本文中给出的项目,可以看出Main.cpp中就是程序的入口WinMain()函数;Application类(包括.h与.cpp两部分)就是 图示的Application;Window类(包括.h与.cpp两部分)就是图示的Window部分;而application变量(在 Application.cpp中声明)就是图中左上角那全局变量。
  也就是说,本项目中的Application、Window两个类再加上一个WinMain()函数就完成了一个Windows程序需要的基本框架。这三个类写定以后,就不需要再作改变(架构意义上而言…)!而我们的后续开发扩展功能的工作,就只需要进行一些简单的添加就能完成(下面马上讲到的MyWin和MyApp两个类的作用),下面就是扩展部分的说明。
  还是先看看第一部分中提到的扩展程序示意图:


  MyApp和MyWin两个类,就是我们自己扩展出来的。实现上图中My Program的功能。可以看到,我们的子类MyWin的OnPaint()方法在运行过程中已经取代了基类Window的OnPaint()方法,替我们输出了一个文本。
   总结一下,整个这个例子想要说明的一个问题就是:如果我们的底层结构(Application、Window两个类)写得足够好了,我们以后的开发只需 要做MyWin和MyApp两个类,在其中添加我们的功能即可,这种添加只需要很少的代码量,如本例中的这两个扩展类其实只有如下的内容,并且结构很清晰。
(MyApp和MyWin类)

class MyApp
namespace inshion {
class MyApp: public inshion::Application {
public:
    MyApp(){}
    
virtual ~MyApp(){}
    
bool InitInstance(){        
        
if (!MainWin.Create(this"Inshion - Test - 001"00)){
            
return FALSE;
        }
        MainWindow 
= &MainWin;        
        
return TRUE;
    }

protected:
    MyWin MainWin;
};

MyApp theApp;
}
class MyWin
namespace inshion {

class MyWin : public inshion::Window{
public:
    MyWin(){}
    
virtual ~MyWin(){}

    LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam){
        
switch (uMsg) {
            
case WM_PAINT:
                OnPaint();
                
break;
            
default:
                
return Window::WindowProc(uMsg, wParam, lParam);
            }
            
return 0L;
    }

    
void OnPaint(){
        PAINTSTRUCT ps;
        HDC hdc;
        hdc 
= BeginPaint(hWnd, &ps);
        PrintText(
"Hello,I'm Inshion~");
        EndPaint(hWnd, 
&ps);
    }
};

}


  另外再提一下,我们可以试着把MyApp.h中的成员变量定义
  MyWin MainWin;
  改回基类
  Window MainWin;
  此时的运行结果就是弹出一个基类的Window,而与MyWin无关(可以把MyWin相关的代码删掉,依然不影响运行)。这一方面说明,如果我们的 很多需求是大量重复的,就完全可以在基类里做好,扩展时都不用写MyWin这样的窗口类;另一方面说明,即使我们要自己做扩展,也是非常方便地添加一个窗 口类就可以。

  下一部分将介绍如何把基类们封装成静态库项目,以便更方便地复用。

附:本文中的源代码项目下载(MyMain_Inshion_Exa001.rar

Copyright © 2024 Inshion
Powered by .NET 9.0 on Kubernetes