没有合适的资源?快使用搜索试试~ 我知道了~
WTL doc
4星 · 超过85%的资源 需积分: 0 95 下载量 15 浏览量
2008-04-14
14:57:44
上传
评论
收藏 419KB DOC 举报
温馨提示
试读
28页
很不错的wtl 开发文档
资源详情
资源评论
资源推荐
WTL Makes UI Programming a Joy
Part 2: The Bells and Whistles
Recall from Part 1 of this series, that the Windows Template Library (WTL) is available on the January 2000
Platform SDK and beyond. It’s an SDK sample produced by members of the ATL team chartered with
building an ATL-based wrapper around the windowing portions of the Win32 API. In Part I, I covered WTL’s
support for SDI, Multi-SDI, MDI, and explorer/workspace-style applications that use command bars, splitters,
GDI wrappers, helper classes, and DDX. In Part II, I’ll give you a look into WTL’s common controls
wrappers, common dialog wrappers, property sheets, printing, print preview, scrolling support, message
cracking, filtering, and idle handling. I will demonstrate these features while building a new sample program:
BmpView.
The BmpView Sample
This sample, called BmpView, displays .BMP files. I created the starting code for BmpView using the Visual
C++ WTL App Wizard. I used the default settings—an SDI application type with a generic view window and
a rebar, a command bar, and a status bar.
Before I start adding features, I need to remove some. Because BmpView should be able to open BMP files,
but doesn't save them (WTL is not PhotoDraw, after all), I need to remove menu items for saving files. I also
need menu items for printing, page setup, and print preview. All these changes require me to modify
resources of the application, adding or removing menu items and toolbar buttons. The modified application
is shown in Figure 1.
Figure 1: The Modified Application
Instead of the built-in Win32 menu bars, the wizard-generated code uses a WTL command bar for that
polished, modern look. Command bars look like a specialized toolbar, but with menu items instead of the
toolbar buttons. Command bars also provide images for drop-down menu items, which assist in recognizing
commands by providing a visual link between a text label and a corresponding toolbar button. Part I showed
how command bars work. In BmpView, I’d like to apply the same nifty graphics to a context menu, which is
what I’ll tackle first.
Context Menus
A context menu should appear when the user right-clicks in the main window. Assuming the context menu
will be created from a resource in your application, it is pretty straightforward how to handle the
WM_CONTEXTMENU message (which is sent when the user right-clicks in the main window) on the main
window and display the menu using TrackPopupMenu windows API. Unfortunately, like the built-in menu
bars, Win32 context menus don’t show images. Luckily, the same class that I use to show the menu
command bar can also be used to show images on a context menu. The command-bar class in WTL,
CCommandBarCtrl
1
, has a method called TrackPopupMenu that you can use to display a context menu,
which is nearly identical to the TrackPopupMenuEx Win32 API function:
BOOL
CCommandBarCtrlImpl::TrackPopupMenu(
HMENU hMenu,
UINT uFlags,
int x,
int y,
LPTPMPARAMS lpParams = NULL)
1
CCommandBarCtrl is defined in atlctlw.h.
Before I can use the TrackPopupMenu method, I need to load the menu resource and get the popup menu
portion of it to display our context menu. While all of that can be done using Win32 API and menu handles, it
is more convenient to have a class that wraps a menu. Luckily, WTL provides such a class. Just like the GDI
classes discussed in Part I, there are two classes that wrap an HMENU: CMenu and CMenuHandle. CMenu is
the managed version and destroys the HMENU when it goes out of scope. CMenuHandle is unmanaged and
does nothing in its destructor.
Let's now see how I use all of this for our context menu. In the main window class, CMainFrame, I'll handle
the WM_CONTEXTMENU message. If the message comes from the view window, I'll load and display the
context menu. Here is the code:
LRESULT CMainFrame::OnContextMenu(
UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
if((HWND)wParam == m_view) {
CMenu menu;
menu.LoadMenu(IDR_CONTEXTMENU);
CMenuHandle menuPopup = menu.GetSubMenu(POPUP_MENU_POSITION);
m_CmdBar.TrackPopupMenu(menuPopup,
TPM_RIGHTBUTTON | TPM_VERPOSANIMATION | TPM_VERTICAL,
GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
}
else bHandled = FALSE;
return 0;
}
You can see that I used CMenu class to load the menu resource. That menu will be automatically destroyed
when the CMenu object goes out of scope. To get the popup menu, I used the unmanaged version,
CMenuHandle. Because the popup menu is a part of the parent menu, there is no need to destroy it
separately. When I have the menu loaded, I use the command bar object, m_CmdBar to call its
TrackPopupMenu method to display the context menu. Because the command bar has all the menu item
images loaded, it will display them next to the appropriate menu item. The app with the context menu,
including the associated images, is shown in Figure 2.
Figure 2: Application with Context Menu
Now I have the code that has all of the UI elements that I need. I can proceed to write the code to display
bitmaps, which is, after all, the main point of the sample.
Scrolling Views
The WTL App Wizard created a view class for us. I will use that class to display bitmaps. The App Wizard
generated class has only an empty OnPaint handler, and that's close to what I need. I just need to
implement the OnPaint handler to display the bitmap. However, bitmaps can be of any size, and that size
can be bigger than the window I have. I need to allow users to scroll and see the whole bitmap.
Scrolling allows you to view different portions of the window than display by default. Some of the standard
Windows controls already provide support for this, so you don't have to do any additional work. But, if you
draw the content of the window yourself like I am, you need to write code to support scrolling. WTL provides
classes to help you implement a window that has built in support for scrolling and makes it much easier to
draw without a regard to what is the current visible area. The classes let you concentrate only on the
presentation area that you want to draw, and ignore the current scroll state of the window.
WTL provides two classes for the basic scrolling support: CScrollImpl, and CScrollWindowImpl.
CScrollImpl is a template class that provides generic scrolling support that you can add to any window
class by deriving from CScrollImpl and chaining to its message map. CScrollWindowImpl derives from
CScrollImpl and CWindowImpl, as well as supplying a message map to provide a full scrolling window
implementation. If you derive from CScrollWindowImpl, you don't also need to derive from some form of
CWindowImpl.
WTL also provides another two classes: CMapScrollImpl and CMapScrollWindowImpl, which, in
addition to scrolling, also support mapping modes for drawing. These classes have the same usage as the
basic ones; CMapScrollImpl derives from CScrollImpl and adds support for the mapping modes;
CMapScrollWindowImpl adds a message map for the full-window implementation. Support for mapping
modes allows you to easily use the coordinate system and units that are the best fit for your content.
Regardless of your scrolling implementation base class, you still need to do two things: set the size of your
content (so the scrolling can happen properly), and do the actual drawing (no amount of template based
classes will ever save you from that). However, you do not have to handle the WM_PAINT message or worry
about which part of the content of your window to draw, relative to the current scroll position. Instead, you
set the SetScrollSize and implement the DoPaint method. Setting the size of the scroll region is done
with any number of overloaded CScrollImpl helper functions called SetScrollSize:
void SetScrollSize(int xMin, int yMin, int xMax, int yMax,
BOOL bRedraw = TRUE);
void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE);
void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE);
void SetScrollSize(SIZE size, BOOL bRedraw = NULL
2
);
2
Yep. That last parameter defaults to NULL instead of TRUE. Unfortunately, this will cause bRedraw to
default to FALSE instead of TRUE when using a SIZE structure.
You should call SetScrollSize whenever the size of your content changes. In the BmpView sample, I do
this when the bitmap to display changes:
class CBitmapView : public CScrollWindowImpl<CBitmapView> {
…
void SetBitmap(HBITMAP hBitmap) {
if(!m_bmp.IsNull()) m_bmp.DeleteObject();
m_bmp = hBitmap;
if(!m_bmp.IsNull()) m_bmp.GetSize(m_size);
else m_size.cx = m_size.cy = 1;
SetScrollOffset(0, 0, FALSE);
SetScrollSize(m_size);
}
…
};
When it’s time to draw, remember that CScrollWindowImpl handles the WM_PAINT message and
forwards it to our DoPaint function. DoPaint will be called with the appropriate Win32 viewport settings to
allow you to draw your content with the upper left hand corner adjusted for the current scroll position. It’s not
really so complicated as it seems, as shown in the CScrollImpl class’s implementation of OnPaint:
LRESULT CScrollImpl::OnPaint(UINT, WPARAM wParam, LPARAM, BOOL&) {
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
if(wParam != NULL) { // The HDC is sometimes passed in
CDCHandle dc = (HDC)wParam;
dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
pT->DoPaint(dc);
}
else {
CPaintDC dc(pT->m_hWnd);
dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
pT->DoPaint(CDCHandle(dc));
}
return 0;
}
Our view’s implementation of DoPaint does pretty much what you’d expect:
class CBitmapView : public CScrollWindowImpl<CBitmapView> {
…
void DoPaint(CDCHandle dc) {
if(!m_bmp.IsNull()) {
CDC dcMem;
dcMem.CreateCompatibleDC(dc);
HBITMAP hBmpOld = dcMem.SelectBitmap(m_bmp);
dc.BitBlt(0, 0, m_size.cx, m_size.cy, dcMem, 0, 0, SRCCOPY);
dcMem.SelectBitmap(hBmpOld);
剩余27页未读,继续阅读
dongzhaoyu
- 粉丝: 1
- 资源: 8
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论3