什么时候调用setMode?
- 初始化阶段的init_video()。
- 要修改朝向。竖屏、横屏切换。
这里说的窗口尺寸变化不包括修改朝向,因而发生后,不会调用setMode。这里要考虑的主要是两种情况。
- 单击左上角的“最大/恢复”按钮。
- 拉着窗口边框,改变尺寸。
以单击左上角的“最大/恢复”按钮为例,看是怎么处理的。
- (SDL)WIN_WIndowProc。收到WM_WINDOWPOSCHANGED消息,调用SDL_OnWindowResized,执行向队列放入SDL_WINDOWEVENT_SIZE_CHANGED事件。
- (SDL)WIN_WIndowProc。收到WM_SIZE(wParam:SIZE_MAXIMIZED)消息。不是向队列放一个新事件,而是调用app挂接的sdl_apphandlers.window_event_handler,后者对应app的handle_window_event。
- (app)base_instance::handle_window_event。发现type是SDL_WINDOWEVENT_MAXIMIZED,preferences的maximized置为true。
- (app)events::pump。收到“event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED”,调用base_instance::handle_resize_screen。
- (app)handle_resize_screen。调用gui2::absolute_draw_all重画窗口,包括place各控件。
在WIN_WIndowProc消息序列上, 是先WM_WINDOWPOSCHANGED,然后SDL_WINDOWEVENT_MAXIMIZED。由于CHANGED是向队列加事件,MAXIMIZED是立即调用app的handle_window_event。在app看来,是先handle_window_event,然后handle_resize_screen。
在处理SIZE_CHANGED,先判断是否正处在最大化,如果是,不要保存x、y到preferences。避免在启动是最大化时,第一次回到常规,还是大窗口。
在最小化时,app会收到SDL_WINDOWEVENT_SIZE_CHANGED吗?——不会。从最小化恢复到常规时,也不会。也就说,这两种情况下,都不会调用app的base_instance::handle_resize_screen。
在base_instance::handle_resize_screen,会调用tdialog的resize_screen(),后者会调用虚函数app_resize_screen()。在某个tdialog,如果有预创建的texture/surface是和尺寸密切相关,那重载app_resiz_screen,内中释放掉这些已存在的,然后重新创建。
对“拉着窗口边框,改变尺寸”,它没有2、3步骤。
场景时
在场景,总体遵循上面逻辑,在第5步会有不同。而且在那里,会分出两种处理方法。
- 和dialog一样,使用重载tdialog::app_resize_screen方法。
- 不使用重载tdialog::app_resize_screen。handle_resize_screen会调用preferences::::set_resolution,在那里把display::require_change_resolution置为true。event::pump发现require_change_resolution是true,调用disp->change_resolution()。过程中,会销毁、并创建新的tdialog,因而不推荐使用。为什么会有这种方法?——有时改变的不仅仅尺寸,而是屏幕分辨率,像要求画质较高的游戏。
<launcher>/health_display.hpp
------
bool use_app_resize_screen() const override { return true; }要让场景时使用app_resize_screen方法,需在xxx_display重载use_app_resize_screen,并返回true。这方法时,app_resize_screen一般用着以下逻辑。
<launcher>/health_controller.cpp
------
void health_controller::app_resize_screen()
{
// 手动重布局窗口
window_->layout();
// 因为重布局了,得到_bit_map控件的矩形:main_map_rect_
gui_->update_main_map_rect();
// 重画大地图背景图像。如果大地图比main_map_rect_小,会露出部分背景图像。
gui_->enable_redraw_background();
// 窗口尺寸变了,为美观,得修正display中的xpos_、ypos_
gui_->fix_xpos_ypos();
// 以下是各窗口私有逻辑了。
make_sure_map();
VALIDATE(curr_chartsel_ != nposm, null_str);
refresh_chart_by_sel(curr_chartsel_);
if (watermark_halo_ != halo::NO_HALO) {
did_watermark_text_changed(*dlg_->watermark_widget().text_box());
}
}