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


第三部分 一个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
namespaceinshion{
classMyApp:publicinshion::Application{
public:
MyApp(){}
virtual~MyApp(){}
boolInitInstance(){
if(!MainWin.Create(this,"Inshion-Test-001",0,0)){
returnFALSE;
}
MainWindow
=&MainWin;
returnTRUE;
}

protected:
MyWinMainWin;
};

MyApptheApp;
}
class MyWin
namespaceinshion{

classMyWin:publicinshion::Window{
public:
MyWin(){}
virtual~MyWin(){}

LRESULTWindowProc(UINTuMsg,WPARAMwParam,LPARAMlParam){
switch(uMsg){
caseWM_PAINT:
OnPaint();
break;
default:
returnWindow::WindowProc(uMsg,wParam,lParam);
}
return0L;
}

voidOnPaint(){
PAINTSTRUCTps;
HDChdc;
hdc
=BeginPaint(hWnd,&ps);
PrintText(
"Hello,I'mInshion~");
EndPaint(hWnd,
&ps);
}
};

}


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

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

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

优质内容筛选与推荐>>
1、RHEL 7 笔记: 2019年11月10日
2、leetcode1091
3、什么是JDBC?
4、[原创]Java并发编程(1):线程基础
5、CF734E Anton and Tree


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn