《白话C++》第11章 我的小画家
《白话C++》第11章 我的小画家,开发过程
yanzhenxi
这个作者很懒,什么都没留下…
展开
-
一个undefined reference to ‘vtable for CruciformItem‘的错误
项目文件夹目录中有item_cruciform.cpp和item_cruciform.hpp这两个文件,然而项目文件列表里面,却没有这两个文件。在项目列表中添加上这两个文件,就不报错了。原创 2024-01-29 13:47:27 · 378 阅读 · 0 评论 -
第11章 GUI Page508~509 步骤三十六:完善“编辑”菜单,方法三,不使用设计视图,完全通过代码实现复制
将“编辑”菜单的变量名改为MenuEdit在wxMyPainterFrame的构造函数尾部添加以下代码:运行效果:原创 2024-01-21 02:43:10 · 346 阅读 · 0 评论 -
第11章 GUI Page508~509 步骤三十六:完善“编辑”菜单,方法一
至此,菜单可以运行了,但是改变图元次序的上浮,下降,置顶,置底的菜单项状态维护还没有成功。在“编辑”菜单下一项项添加,然后再将新菜单项的事件挂接到现有菜单项的函数上。为“置顶,上浮,下降,置底,删除,隐藏”菜单绑定现有的菜单项的函数上。注意:“隐藏”菜单的类型是Check。为隐藏菜单绑定“菜单项更新”原创 2024-01-21 01:34:48 · 358 阅读 · 0 评论 -
第11章 GUI Page507 步骤三十五:处理应用退出事件
为wxFrame,生成一个EVT_CLOSE事件响应函数:实现如下:运行效果:关闭时,会弹出对话框询问是否保存原创 2024-01-20 20:08:05 · 373 阅读 · 0 评论 -
第11章 GUI Page504~506 步骤三十三,三十四:剪贴板实现
变量名称及菜单ID分别为:MenuItemEditCut / idMenuEditCut MenuItemEditCopy / idMenuEditCopy MenuItemEditPaste / idMenuEditPaste。对应的热键(快捷键)分别为 Ctrl+X,Ctrl+C,Ctrl+V。原创 2024-01-20 13:34:50 · 385 阅读 · 0 评论 -
第11章 GUI Page500~504 步骤三十二:打开画板文件02
程序运行时,发现打开 方框 和 文字时,会出异常。原创 2024-01-19 22:34:54 · 364 阅读 · 0 评论 -
第11章 GUI Page496~498 步骤三十二:打开画板文件01
tool_4_save_load.hpp添加新内容:源文件中,新增的四个函数实现为:为各图元类加上从流中加载图元数据的功能,先是接口声明:各图元实现接口:直线:圆:十字形:方框:文字:原创 2024-01-13 18:19:09 · 369 阅读 · 0 评论 -
第11章 GUI Page495~496 步骤三十一:另存为别的文件,为TrySaveFile()入参设置一些位操作
工程二头文件中为TrySaveFile()入参设置一些位操作,修改一下TrySaveFile()的入参类型修改TrySaveFile()的实现:修改“保存”菜单项挂接事件响应函数:修改“另存为”菜单项挂接事件响应函数原创 2024-01-12 22:59:05 · 370 阅读 · 0 评论 -
第11章 GUI Page495~496 步骤三十一:另存为别的文件
当前的TrySaveFile(bool hint_on_dirty = true)有两个特征无法满足“另存”的需求:一,TrySaveFile仅在数据为“新”的时候才提问用户输入文件名。而“另存”总是要求用户输入一个文件名,多以它总应该弹出一个文件选择对话框,这也正是菜单标题带有“...”的暗示的原因。二,TrySaveFile仅在文件确实有仍未保存新修改(即数据为“脏”)时,才真实的执行保存操作,否则它将聪明地直接返回。原创 2024-01-12 21:04:51 · 384 阅读 · 0 评论 -
第11章 GUI Page489~494 步骤三十 保存画板文件02 实现存盘函数SaveFile
工程添加新头文件tool_4_save_load.hpp增加源文件 tool_4_save_load.cppIItem类增加保存到流的接口:在直线,圆,十字形,方框,文字类中实现这个接口回到主框架窗口,实现保存文件的函数SaveFile首先封装一个函数,SaveFile中要用到实现SaveFile运行效果:使用记事本打开保存的文件,内容如下原创 2024-01-12 15:38:16 · 359 阅读 · 0 评论 -
第11章 GUI Page489~494 步骤三十 保存画板文件
可以看到“保存对话框”的细节不够完善,一是不能指定我们特有的扩展名“.d2mp”;而是命名保存,但主按钮的标题却是“打开”。原创 2024-01-12 02:56:50 · 409 阅读 · 0 评论 -
第11章 GUI Page488~489 步骤二十八,二十九 新建画板文件
文件”主菜单项下,添加 新建,打开,保存,另存为 等菜单项。ActionLink增加一个重置函数Reset。点击“新建”之后,窗口标题的 * 没有了。原创 2024-01-12 00:50:43 · 377 阅读 · 0 评论 -
第11章 GUI Page487 步骤二十七 “脏数据”与“新文档”状态维护 代码重构
这些位置分别在下面的函数中//鼠标抬起函数void wxMyPainterFrame::OnScrolledWindow1LeftUp(wxMouseEvent& event)//置顶void wxMyPainterFrame::OnMenuItemTopLevelSelected(wxCommandEvent& event)//上浮void wxMyPainterFrame::OnMenuItemFowardLevelSelected(wxCommandEvent& event)//下降void原创 2024-01-11 20:21:57 · 357 阅读 · 0 评论 -
第11章 GUI Page480~487 步骤二十七 “脏数据”与“新文档”状态维护
wxMyPainterFrame类中,修改了“_items”的几个地方① 鼠标抬起时,添加新元素;② 删除事件;③ 置顶,上浮一层,下沉一层,置底四个事件中,修改了元素位置;④ 隐藏事件中,修改了元素的可视属性。原创 2024-01-08 23:40:41 · 428 阅读 · 0 评论 -
第11章 GUI Page462~476 步骤二十三,二十四,二十五 Undo/Redo ⑦“上浮,下降” 支持 “Undo/Redo”
工程十:上浮事件函数下降事件函数完成Swap()函数修改 Undo()修改 Redo()原创 2024-01-08 01:29:35 · 316 阅读 · 0 评论 -
第11章 GUI Page462~476 步骤二十三,二十四,二十五 Undo/Redo ⑥“置底操作”支持“Undo/Redo”
工程九置顶事件响应函数中,增加一行完成UnBottom(), ReBottom()函数Undo() Redo()函数里增加新内容运行效果:原创 2024-01-08 00:52:41 · 365 阅读 · 0 评论 -
第11章 GUI Page462~476 步骤二十三,二十四,二十五 Undo/Redo ⑤“置顶操作”支持“Undo/Redo”
工程八置顶事件响应函数中,增加一行增加调序操作类IndexAction实现构造函数实现UnTop()实现ReTop()实现Undo() Redo()运行效果:原创 2024-01-07 22:46:16 · 382 阅读 · 0 评论 -
第11章 GUI Page462~476 步骤二十三,二十四,二十五 Undo/Redo ④“删除操作”支持“Undo/Redo”
工程七在删除事件响应函数中,添加一行添加一个DelAction类实现DelAction类的构造函数,析构函数,和虚成员函数运行效果:原创 2024-01-07 15:59:38 · 388 阅读 · 0 评论 -
第11章 GUI Page462~476 步骤二十三,二十四,二十五 Undo/Redo ③实现“Undo/Redo”菜单项
菜单ID分别为 idMenuEditUndo 和 idMenuEditRedo热键(快捷键)分别为Ctrl+Z 和 Ctrl+Shift+Z变量名分别为 MenuItemEditUndo 和 MenuItemEditRedo。原创 2024-01-07 02:01:12 · 385 阅读 · 0 评论 -
第11章 GUI Page462~476 步骤二十三,二十四,二十五 Undo/Redo ②“添加操作”支持“Undo/Redo”
所以我们还需要在基类EditAction增加响应的成员函数,另外再实现AddAction(EditAction* newAction)编译报错:action_link.cpp:10: undefined reference to `EditAction::~EditAction()' 因为~EditAction()还是纯虚函数,还未实现原创 2024-01-06 02:20:48 · 411 阅读 · 0 评论 -
第11章 GUI Page462~476 步骤二十三,二十四,二十五 Undo/Redo ①为Undo/Redo做准备工作,弹出日志窗口
编译之后,报错error: 'struct ActionLink' has no member named 'AddAction' 没有成员函数error: expected type-specifier before 'AddAction' 没有类型标识符。原创 2024-01-05 22:29:56 · 405 阅读 · 0 评论 -
第11章 GUI Pag459 步骤二十一:课堂作业,支持在画图状态下,也能选中图元
所以,如果图元的菜单项没有被选中,那么268行的_newItem是nullptr, 于是才能进入270行的if判断中。要想保证能进入271行,必须保证268行的_newItem是nullptr。创建 _newItem的过程:238行,首先检查图元的菜单项是否选中,选中了,才会创建图元。鼠标抬起的过程中,如果图元太小,则将图元干掉,反之,则将_newItem添加到列表中。原创 2024-01-03 20:25:13 · 336 阅读 · 0 评论 -
第11章 GUI Page458~459 步骤二十一:为画板上鼠标左击添加新逻辑,十字形,方框,圆,文字。
运行效果:现在组件菜单中,选中无,然后就可发现,画出的图元可以选中了。原创 2024-01-03 16:50:31 · 344 阅读 · 0 评论 -
第11章 GUI Page458~459 步骤二十一:为画板上鼠标左击添加新逻辑,直线
增加一些代码,由于我们在组件菜单中,默认选中的是“直线”,所以在268行,我们按下鼠标时,一定会创建一个_newItem, 所以269行,_newItem一定不空,所以270~277hand的代码,肯定不会执行,所以,如果我们要想选中图元,在画出图元后,必须在组件菜单中,选中"无"菜单项。运行效果:画三条直线后,再在组件菜单里,切换成菜单项“无”,再在直线上点一下,就可以选中直线上。增加新的成员函数HitTest()原创 2024-01-03 15:59:33 · 343 阅读 · 0 评论 -
第11章 GUI Page455~458 步骤二十:实现各类图元的“命中”判断
一旦为IItem添加一个纯虚的接口,比如前述的 IsHitOn(), 就意味着我们不得不为所有当前已经存在的派生类都实现该接口之后,程序才能够编译通过,运行起来接受测试。小窍门是暂时将IItem::IsHitOn 改成一个空的实现,默认返回false。等后续完成各派生类实现了,才将它恢复成纯虚接口, 不推荐这样做,推荐的做法是为每个派生类写一个空的实现,先简单返回false。小提示:在已经有不少派生类的情况下调试基类的新接口。原创 2024-01-03 15:20:43 · 373 阅读 · 0 评论 -
第11章 GUI Page453 步骤十九:自动维护弹出菜单项状态
接下来处理所有改变图元次序的菜单项状态维护,它们没有选中状态,只有是否可用的状态。我们将一次绑定所有的四个菜单项,所以请在源文件中查找生成ID_POPMENU_TOP和ID_POPMENU_BOTTOM等ID的四行代码,确保它们相邻。逻辑是:如果当前没有选中项,则“隐藏”菜单项设置为不可用状态,即代码中的event.Enable(false) , 同时确保它不处于选中状态;运行效果:可以看到,选中最上层图元时,置顶和上浮菜单项是灰色(不可用)状态。没有选中任何图元,所以删除菜单处于灰色状态。原创 2024-01-01 17:23:17 · 314 阅读 · 0 评论 -
第11章 GUI Page452 步骤十八:实现“隐藏”图元功能,首先实现隐藏直线,再实现隐藏其他图元
构造的图元的方法中,添加注释,只保留创建直线的宏,因为其他图元类中的接口方法还没有实现,是抽象类,不能够创建对象。直线类中,增加一个私有成员_visible, 并在构造时初始化它,即构造时,是可视化的。首先需要强调一下:菜单项“隐藏”的类型是Check, 否则,就会出各种错误。item_i.hpp中,接口类IItem中需要增加两个接口,然后,修改画直线的方法,根据是否可见,然后决定是否画直线。为菜单项“隐藏”绑定响应函数,并实现它。原创 2024-01-01 01:01:16 · 340 阅读 · 0 评论 -
第11章 GUI Page452 步骤十七:次序调整与删除操作 在源头位置处理数据的变化,课堂作业,实现下降,置底,以及删除
为菜单项“下降”绑定响应函数,并实现它。为菜单“置底”绑定响应函数,并实现它。为菜单项“删除”绑定响应函数,并实现。运行效果:仅显示删除效果。原创 2023-12-31 01:38:43 · 331 阅读 · 0 评论 -
寻找错误,解决上浮和置顶效果一样的问题的过程
这两个被框住的代码的含义是,先画出没有被选中的图元,然后根据_selected_item_visible的值,决定是否画出被选中的图元,这就是导致上浮功能异常的原因,于是把Opaint的代码修改为书中原有的代码。又仔细比对了一下上浮函数的代码,没发现错误。发现矩形0 却上浮到了最顶层,但是左边列表框内的次序是正确的,说明错误应该发生在,重新绘制所有矩形的代码内。这样功能就正常了,只是解决被覆盖图元不闪烁,和上浮有些矛盾,所以代码还需要改善,以后再改善吧。在上浮菜单事件中,增加一条输出信息,原创 2023-12-30 13:14:43 · 320 阅读 · 0 评论 -
第11章 GUI Page450~451 步骤十七:次序调整与删除操作 在源头位置处理数据的变化,上浮的实现
上浮效果和置顶的效果一样?“上浮”一层的事件响应函数则为。原创 2023-12-30 13:12:17 · 353 阅读 · 0 评论 -
第11章 GUI Page448 步骤十七:次序调整与删除操作 “置顶”
给“置顶”绑定选择事件。原创 2023-12-27 21:04:45 · 376 阅读 · 0 评论 -
第11章 GUI Page446~447 步骤十六:挂接列表框右键事件
原因:键盘,鼠标等事件,是直接发送到各种“Control(控件)”(在Windows下,指拥有句柄,拥有自行的消息处理函数的各种窗口),除非该控件的实现代码,在处理这些消息时,将其转换成“COMMAND(命令)”类型的事件。这类事件如果当前控件不响应它,默认是向它的父窗口传播(如果父窗口又没有处理,就传给“爷爷”窗口),而其他事件则直接被源控件“吃掉”,比如鼠标单击或键盘事件。编译,运行,加入一条线,右击列表框,没看到消息框弹出,事件绑定失败。在cpp文件中提供一个实现。原创 2023-12-27 19:22:37 · 386 阅读 · 0 评论 -
第11章 GUI Page445 步骤十五:设计右键弹出菜单
添加菜单项,并按照书上提供的菜单名和菜单ID命名(446页,上浮和下降的命名搞反了,可能是排版错误)进入项目的wxSmith设计视图,先添加一个wxMenu菜单组件,命名为MenuListBox。原创 2023-12-27 16:39:32 · 339 阅读 · 0 评论 -
第11章 GUI Page444 步骤十四:让闪烁功能成为一个用户选项
为“设置”添加一条分隔线,再添加一个“选中时闪烁”的菜单项,菜单类型为Check,且初始设计为选中状态,菜单项变量取名MenuItemFlash。为菜单项绑定一个时间响应函数,闪烁功能是通过定时器实现的,根据该菜单项是否选中,暂停或者恢复定时器。原创 2023-12-27 15:16:58 · 350 阅读 · 0 评论 -
第11章 GUI Page444 步骤十四:课堂作业,解决被覆盖的图元不闪烁的问题
先把没有被选中的图元画出来,再根据_selected_item_visible的值,决定是否画出被选中的图元。只需要稍微修改一下窗口的OnPaint函数就可以了。解决被覆盖的图元不闪烁的问题。原创 2023-12-27 12:30:32 · 312 阅读 · 0 评论 -
第11章 GUI Page442~444 步骤十四:闪烁选中图元
选中图元闪烁。原创 2023-12-27 12:12:32 · 321 阅读 · 0 评论 -
第11章 GUI Page440~442 步骤十三:屏蔽小图元
运行效果:关键代码:IItem类中,新增一个接口线,圆,方块,文字,十字类中实现接口线圆方块文字十字在窗口类中,鼠标抬起函数中使用 IsLargeEnough()原创 2023-12-26 22:58:34 · 368 阅读 · 0 评论 -
第11章 GUI Page439 步骤十二 为图元编号 支持所有图形
运行效果:关键代码:圆:方框:文字:十字:原创 2023-12-25 22:43:13 · 367 阅读 · 0 评论 -
第11章 GUI Page439 步骤十二 为图元编号 支持直线
为直线类,新增一个_index成员,并实现GetIndex和SetIndex两个函数。原创 2023-12-25 21:19:18 · 391 阅读 · 0 评论 -
第11章 GUI Page437~438 步骤十一 列出图元 支持矩形,圆,十字,文字
创建新图元的代码中,放开所有的注释:原创 2023-12-25 16:37:22 · 341 阅读 · 0 评论