#include "StdAfx.h" #include "T2DLL/GlobalFunc.h" #include "T2DLL/T2BitImage.h" #include "T2DLL/T2ImageObj.h" #include "T2DLL/T2PluginLoader.h" #include "T2DLL/T2PluginSpecifier.h" #include "T2TowerDoc.h" #include "T2WorldSelectDlg.h" #include "Resource.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif T2WorldSelectDlg::T2WorldSelectDlg() { mDeleteOnClose = true; HRSRC rsrc = FindResource(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDR_DEFAULT_PALETTE), "PALETTE"); HGLOBAL theHandle = LoadResource(AfxGetApp()->m_hInstance, rsrc); void *resData = LockResource(theHandle); LOGPALETTE *theLogPalette = ConvACTPalette((ACTPALETTEENTRY *) resData); mPalette.CreatePalette(theLogPalette); int i; mPal1 = (short *) malloc(sizeof(short) * 256); for (i = 0; i < 256; i++) mPal1[i] = i; mPal2 = (short *) malloc(sizeof(short) * 256); for (i = 0; i < 256; i++) { int r = theLogPalette->palPalEntry[i].peRed; int g = theLogPalette->palPalEntry[i].peGreen; int b = theLogPalette->palPalEntry[i].peBlue; int index = mPalette.GetNearestPaletteIndex(RGB(r, g, b)); if (theLogPalette->palPalEntry[index].peRed == 1 && theLogPalette->palPalEntry[index].peGreen == 1 && theLogPalette->palPalEntry[index].peBlue == 1) index = 255; mPal2[i] = index; } free(theLogPalette); mBitmap.LoadBitmap(IDB_PATTERN_BRUSH); mBrush.CreatePatternBrush(&mBitmap); mPlugins = NULL; mScrollOffset = 0; mSelectedPlugin = 0; } /*virtual*/ T2WorldSelectDlg::~T2WorldSelectDlg() { if (mPlugins) { for (int i = 0; i < mPluginCount; i++) { delete mPlugins[i].preview; delete mPlugins[i].icon; delete mPlugins[i].mStr8; delete mPlugins[i].mStr18; delete mPlugins[i].mStrC; delete mPlugins[i].mStr10; delete mPlugins[i].mStr14; } free(mPlugins); } free(mPal1); free(mPal2); mBrush.DeleteObject(); mBitmap.DeleteObject(); if (mImageObj) delete mImageObj; if (mArrowButtonImages) delete mArrowButtonImages; } void T2WorldSelectDlg::ShowWorldSelectDlg(T2TowerDoc *inDoc, T2PluginLoader *inPluginLoader, BOOL inShowCancelButton) { mDocument = inDoc; mPluginLoader = inPluginLoader; mShowCancelButton = inShowCancelButton; POSITION pos; T2PluginSpecifier *specifier; mPluginLoader->SetTypeFilter(pos, 'WdPl'); mPluginCount = 0; while ((specifier = mPluginLoader->GetNext(pos))) mPluginCount++; mPlugins = (PluginRecord *) malloc(mPluginCount * sizeof(PluginRecord)); mPluginLoader->SetTypeFilter(pos, 'WdPl'); int index = 0; while ((specifier = mPluginLoader->GetNext(pos))) { mPluginLoader->LoadPlugin(specifier); #line 107 mPlugins[index].preview = new T2BitImage(specifier->mInstance, 20000, false); mPlugins[index].icon = new T2BitImage(specifier->mInstance, 20001, false); mPlugins[index].mStr8 = new CString(specifier->mPluginName); char *buf = (char *) malloc(10000); strcpy(buf, "NO TEXT|?\n?\n?"); LoadString(specifier->mInstance, 20000, buf, 10000); #line 113 mPlugins[index].mStr18 = new CString(strtok(buf, "|")); mPlugins[index].mStrC = new CString(strtok(NULL, "\r\n")); mPlugins[index].mStr10 = new CString(strtok(NULL, "\r\n")); mPlugins[index].mStr14 = new CString(strtok(NULL, "\r\n")); free(buf); mPluginLoader->UnloadPlugin(specifier); index++; } CRect rect; GetDesktopWindow()->GetWindowRect(rect); HMODULE instanceHandle = AfxGetInstanceHandle(); T2DLGTEMPLATE tmpl; tmpl.pt = rect.CenterPoint(); tmpl.moduleHandle = instanceHandle; tmpl.resID = kDlgResID; mDocumentAlso = NULL; #line 134 mImageObj = new T2ImageObj; mArrowButtonImages = new T2BitImage(instanceHandle, IDB_WORLD_SELECT, true); mImageObj->AddObject(instanceHandle, IDB_WORLD_SELECT, mArrowButtonImages); Realize(this, &tmpl, mDocumentAlso, mImageObj, &mPalette, true, NULL, 0, true); mBackButton = (CButton *) GetDescendantWindow(kCmdLeft); mNextButton = (CButton *) GetDescendantWindow(kCmdRight); mBackButton->EnableWindow(false); } /*virtual*/ BOOL T2WorldSelectDlg::PreCreateWindow(CREATESTRUCT &cs) { return T2Dialog::PreCreateWindow(cs); } T2PluginSpecifier *T2WorldSelectDlg::GetSelectedPlugin() { POSITION pos; T2PluginSpecifier *specifier; int index = mSelectedPlugin; mPluginLoader->SetTypeFilter(pos, 'WdPl'); while ((specifier = mPluginLoader->GetNext(pos))) { if (index == 0) break; index--; } return specifier; } /*virtual*/ BOOL T2WorldSelectDlg::OnT2PreEraseBkgnd(CDC *pDC) { #pragma var_order(brush3, bitmap, newSave2, pen2, newSave, pen3, brush1, save, newDC, index, pen1, rectB, rectA, maxPlugin, brush2) CRect rectA, rectB; GetWindowRect(rectA); ScreenToClient(rectA); GetClientRect(mRect3); mRect3.left = 0; mRect3.top = 0; mRect3.right = 488; mRect3.bottom = 364; mRect1.left = 30; mRect1.top = 253; mRect1.right = 458; mRect1.bottom = 321; mRect2.left = 12; mRect2.top = 11; mRect2.right = 476; mRect2.bottom = 238; int save = pDC->SaveDC(); pDC->SelectPalette(&mPalette, false); pDC->RealizePalette(); CBitmap bitmap; bitmap.CreateCompatibleBitmap(pDC, mRect3.Width(), mRect3.Height()); CDC newDC; newDC.CreateCompatibleDC(pDC); int newSave = newDC.SaveDC(); newDC.SelectObject(bitmap); newDC.SelectPalette(&mPalette, false); newDC.RealizePalette(); newDC.SetStretchBltMode(COLORONCOLOR); CBrush brush1, brush2, brush3; brush1.CreateSolidBrush(PALETTERGB(204, 204, 204)); brush2.CreateSolidBrush(PALETTERGB(255, 255, 255)); brush3.CreateSolidBrush(PALETTERGB(200, 0, 0)); CPen pen1, pen2, pen3; pen1.CreatePen(PS_SOLID, 0, PALETTERGB(255, 255, 255)); pen2.CreatePen(PS_SOLID, 0, PALETTERGB(133, 133, 133)); pen3.CreatePen(PS_SOLID, 0, PALETTERGB(0, 0, 0)); newDC.FillRect(mRect3, &brush1); newDC.SelectObject(brush2); newDC.SelectObject(pen3); newDC.Rectangle(mRect1.left + 1, mRect1.top + 1, mRect1.right - 1, mRect1.bottom - 1); newDC.SelectObject(pen2); newDC.MoveTo(mRect1.right - 1, mRect1.top); newDC.LineTo(mRect1.left, mRect1.top); newDC.LineTo(mRect1.left, mRect1.bottom); newDC.SelectObject(pen1); newDC.MoveTo(mRect1.left, mRect1.bottom - 1); newDC.LineTo(mRect1.right - 1, mRect1.bottom - 1); newDC.LineTo(mRect1.right - 1, mRect1.top); int maxPlugin = min(mScrollOffset + 6, mPluginCount); for (int index = mScrollOffset; index < maxPlugin; index++) { #pragma var_order(rect2, x, rect1) int x = (index - mScrollOffset) * 70 + mRect1.left + 2; CRect rect1; rect1.SetRect(x, mRect1.top + 2, x + 70, mRect1.bottom - 2); CRect rect2; rect2.top = rect1.CenterPoint().y - mPlugins[index].icon->mBitmap.header.biHeight / 2; rect2.left = rect1.CenterPoint().x - mPlugins[index].icon->mBitmap.header.biWidth / 2; rect2.bottom = rect2.top + mPlugins[index].icon->mBitmap.header.biHeight; rect2.right = rect2.left + mPlugins[index].icon->mBitmap.header.biWidth; if (index == mSelectedPlugin) { CRect rect3 = rect2; rect3.top -= 2; rect3.left -= 2; rect3.bottom += 2; rect3.right += 2; newDC.FillRect(rect3, &brush3); } memcpy(&mPlugins[index].icon->mBitmap.palette, mPal2, sizeof(short) * 256); newDC.SelectObject(mBrush); StretchDIBits( newDC.m_hDC, rect2.left, rect2.top, rect2.Width(), rect2.Height(), 0, 0, mPlugins[index].icon->mBitmap.header.biWidth, mPlugins[index].icon->mBitmap.header.biHeight, mPlugins[index].icon->mData, (const BITMAPINFO *) &mPlugins[index].icon->mBitmap, DIB_PAL_COLORS, SRCCOPY ); } #pragma var_order(brush3, bitmap, newSave2, pen2, newSave, pen3, brush1, save, newDC, index, pen1, rectB, rectA, maxPlugin, brush2) int newSave2 = newDC.SaveDC(); newDC.SetViewportOrg(mRect2.TopLeft()); newDC.SetViewportExt(mRect2.Width(), mRect2.Height()); DrawWorldPreview(&newDC); newDC.RestoreDC(newSave2); pDC->BitBlt(0, 0, mRect3.Width(), mRect3.Height(), &newDC, 0, 0, SRCCOPY); x432436(pDC); newDC.RestoreDC(newSave); pDC->RestoreDC(save); return true; } void T2WorldSelectDlg::GoLeft() { #pragma var_order(bitmap, newSave, brush, save, newDC, i, left, pDC) if (mSelectedPlugin <= 0) return; mSelectedPlugin--; if (mSelectedPlugin < mScrollOffset) mScrollOffset = mSelectedPlugin; if (mSelectedPlugin == 0) { mBackButton->EnableWindow(false); SetFocus(); } else { mBackButton->EnableWindow(true); } if (mSelectedPlugin < (mPluginCount - 1)) mNextButton->EnableWindow(true); InvalidateRect(mRect1); UpdateWindow(); CDC *pDC = GetDC(); int save = pDC->SaveDC(); CBrush brush; brush.CreateSolidBrush(PALETTERGB(204, 204, 204)); CBitmap bitmap; bitmap.CreateCompatibleBitmap(pDC, mRect3.Width(), mRect3.Height()); CDC newDC; newDC.CreateCompatibleDC(pDC); int newSave = newDC.SaveDC(); newDC.SelectObject(bitmap); newDC.SelectPalette(&mPalette, false); newDC.RealizePalette(); newDC.SetStretchBltMode(COLORONCOLOR); DrawWorldPreview(&newDC); int left = mRect2.left; for (int i = 1; i <= 10; i++) { #pragma var_order(right, rect2) int right = mRect2.left + ((mRect3.right - mRect2.left) * i) / 10; pDC->BitBlt(right, mRect2.top, mRect2.Width(), mRect2.Height(), pDC, left, mRect2.top, SRCCOPY); left = right; pDC->BitBlt(mRect2.left, mRect2.top, right - mRect2.left, mRect2.Height(), &newDC, 0, 0, SRCCOPY); if (right >= mRect2.right) { CRect rect; rect.SetRect(mRect2.right, mRect2.top, mRect3.right, mRect2.bottom); pDC->FillRect(rect, &brush); } CRect rect2; rect2.left = mRect2.right; rect2.top = mRect2.top; rect2.right = mRect3.right; rect2.bottom = mRect2.bottom; InvalidateRect(rect2); Sleep(30); } newDC.RestoreDC(newSave); pDC->RestoreDC(save); ReleaseDC(pDC); } void T2WorldSelectDlg::GoRight() { #pragma var_order(bitmap, newSave, brush, save, newDC, i, pDC) if (mSelectedPlugin >= (mPluginCount - 1)) return; mSelectedPlugin++; if (mSelectedPlugin >= (mScrollOffset + 6)) mScrollOffset = mSelectedPlugin - 5; if (mSelectedPlugin != 0) mBackButton->EnableWindow(true); if (mSelectedPlugin < (mPluginCount - 1)) { mNextButton->EnableWindow(true); } else { mNextButton->EnableWindow(false); SetFocus(); } InvalidateRect(mRect1); UpdateWindow(); CDC *pDC = GetDC(); int save = pDC->SaveDC(); CBrush brush; brush.CreateSolidBrush(PALETTERGB(204, 204, 204)); CBitmap bitmap; bitmap.CreateCompatibleBitmap(pDC, mRect3.Width(), mRect3.Height()); CDC newDC; newDC.CreateCompatibleDC(pDC); int newSave = newDC.SaveDC(); newDC.SelectObject(bitmap); newDC.SelectPalette(&mPalette, false); newDC.RealizePalette(); newDC.SetStretchBltMode(COLORONCOLOR); DrawWorldPreview(&newDC); for (int i = 1; i <= 10; i++) { #pragma var_order(x, rect2) int x = mRect3.right - ((mRect3.right - mRect2.left) * i) / 10; pDC->BitBlt(x, mRect2.top, mRect2.Width(), mRect2.Height(), &newDC, 0, 0, SRCCOPY); x += mRect2.Width(); if (x < mRect3.right) { CRect rect; rect.SetRect(x, mRect2.top, mRect3.right, mRect2.bottom); pDC->FillRect(rect, &brush); } CRect rect2; rect2.left = x; rect2.top = mRect2.top; rect2.right = mRect3.right; rect2.bottom = mRect2.bottom; InvalidateRect(rect2); UpdateWindow(); Sleep(30); } newDC.RestoreDC(newSave); pDC->RestoreDC(save); ReleaseDC(pDC); } /*virtual*/ void T2WorldSelectDlg::OnT2DlgLButtonDown(UINT nFlags, CPoint pt) { if (PtInRect(mRect1, pt)) { pt.x -= mRect1.TopLeft().x; int index = pt.x / 70 + mScrollOffset; if (index < 0) index = 0; else if (index >= mPluginCount) index = mPluginCount - 1; while (mSelectedPlugin < index) GoRight(); while (index < mSelectedPlugin) GoLeft(); } } /*virtual*/ void T2WorldSelectDlg::OnT2DlgLButtonDblClk(UINT nFlags, CPoint pt) { if (PtInRect(mRect1, pt)) { OnT2DlgLButtonDown(nFlags, pt); OnT2DialogCommand(kCmdOK, 0); } } void T2WorldSelectDlg::DrawWorldPreview(CDC *pDC) { #pragma var_order(pt2, clr1, str, brush3, rect1, pen2, clr2, rect3, pen3, brush1, font, previewWidth, rect2, clr3, save, x, previewHeight, pen4, pen1, pt, brush2) CRect rect1 = mRect2; rect1.OffsetRect(-rect1.left, -rect1.top); int save = pDC->SaveDC(); pDC->SelectPalette(&mPalette, false); pDC->RealizePalette(); CBrush brush1, brush2, brush3; brush1.CreateSolidBrush(PALETTERGB(204, 204, 204)); brush2.CreateSolidBrush(PALETTERGB(255, 255, 255)); brush3.CreateSolidBrush(PALETTERGB(200, 0, 0)); CPen pen1, pen2, pen3, pen4; pen1.CreatePen(PS_SOLID, 0, PALETTERGB(255, 255, 255)); pen2.CreatePen(PS_SOLID, 0, PALETTERGB(133, 133, 133)); pen3.CreatePen(PS_SOLID, 0, PALETTERGB(0, 0, 0)); pen4.CreatePen(PS_SOLID, 0, PALETTERGB(0, 0, 0)); COLORREF clr1 = PALETTERGB(255, 255, 255); COLORREF clr2 = PALETTERGB(133, 133, 133); COLORREF clr3 = PALETTERGB(0, 0, 0); pDC->FillRect(rect1, &brush1); pDC->SelectObject(pen1); pDC->MoveTo(rect1.right - 1, rect1.top); pDC->LineTo(rect1.left, rect1.top); pDC->LineTo(rect1.left, rect1.bottom); pDC->MoveTo(rect1.right - 1, rect1.top + 1); pDC->LineTo(rect1.left + 1, rect1.top + 1); pDC->LineTo(rect1.left + 1, rect1.bottom); pDC->SelectObject(pen2); pDC->MoveTo(rect1.right - 1, rect1.top + 1); pDC->LineTo(rect1.right - 1, rect1.bottom - 1); pDC->LineTo(rect1.left - 1, rect1.bottom - 1); pDC->MoveTo(rect1.right - 2, rect1.top + 2); pDC->LineTo(rect1.right - 2, rect1.bottom - 2); pDC->LineTo(rect1.left, rect1.bottom - 2); CRect rect2; int previewWidth = mPlugins[mSelectedPlugin].preview->mBitmap.header.biWidth; int previewHeight = mPlugins[mSelectedPlugin].preview->mBitmap.header.biHeight; rect2.top = (rect1.Height() - previewHeight) / 2; rect2.left = rect2.top - rect1.top; rect2.bottom = rect2.top + previewHeight; rect2.right = rect2.left + previewWidth; pDC->SelectObject(pen2); pDC->MoveTo(rect2.right, rect2.top - 1); pDC->LineTo(rect2.left - 1, rect2.top - 1); pDC->LineTo(rect2.left - 1, rect2.bottom + 1); pDC->SelectObject(pen1); pDC->MoveTo(rect2.right, rect2.top); pDC->LineTo(rect2.right, rect2.bottom); pDC->LineTo(rect2.left - 2, rect2.bottom); pDC->DrawText("PREVIEW", rect2, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); StretchDIBits( pDC->m_hDC, rect2.left, rect2.top, rect2.Width(), rect2.Height(), 0, 0, previewWidth, previewHeight, mPlugins[mSelectedPlugin].preview->mData, (const BITMAPINFO *) &mPlugins[mSelectedPlugin].preview->mBitmap, DIB_PAL_COLORS, SRCCOPY ); CPoint pt; pt.x = rect2.right + (rect2.left - rect1.left); pt.y = rect2.left; pDC->SetBkMode(TRANSPARENT); CFont font; font.CreateFont(-20, 0, 0, 0, FW_BOLD, false, false, false, SHIFTJIS_CHARSET, OUT_TT_PRECIS, CLIP_TT_ALWAYS, PROOF_QUALITY, DEFAULT_PITCH, "\x82\x6C\x82\x72 \x82\x6F\x83\x53\x83\x56\x83\x62\x83\x4E"); CString str = *mPlugins[mSelectedPlugin].mStr8; pDC->SelectObject(font); pDC->SetTextColor(clr1); pDC->TextOut(pt.x - 1, pt.y - 1, str); pDC->SetTextColor(clr2); pDC->TextOut(pt.x + 1, pt.y + 1, str); pDC->SetTextColor(clr3); pDC->TextOut(pt.x, pt.y, str); font.Detach(); font.CreateFont(-14, 0, 0, 0, FW_BOLD, false, false, false, SHIFTJIS_CHARSET, OUT_TT_PRECIS, CLIP_TT_ALWAYS, PROOF_QUALITY, DEFAULT_PITCH, "\x82\x6C\x82\x72 \x82\x6F\x83\x53\x83\x56\x83\x62\x83\x4E"); pDC->SelectObject(&font)->DeleteObject(); pt.y += 38; pt.x += 12; CPoint pt2 = pt; str = "\x8F\x89\x8A\xFA\x8E\x91\x8B\xE0"; pDC->SetTextColor(clr1); pDC->TextOut(pt.x + 1, pt.y + 1, str); pDC->SetTextColor(clr3); pDC->TextOut(pt.x, pt.y, str); pt.y += 23; str = "\x8D\x82\x82\xB3\x90\xA7\x8C\xC0"; pDC->SetTextColor(clr1); pDC->TextOut(pt.x + 1, pt.y + 1, str); pDC->SetTextColor(clr3); pDC->TextOut(pt.x, pt.y, str); pt.y += 23; str = "\x89\xA1\x95\x9D"; pDC->SetTextColor(clr1); pDC->TextOut(pt.x + 1, pt.y + 1, str); pDC->SetTextColor(clr3); pDC->TextOut(pt.x, pt.y, str); pt.y += 23; str = "\x89\xF0\x90\xE0"; pDC->SetTextColor(clr1); pDC->TextOut(pt.x + 1, pt.y + 1, str); pDC->SetTextColor(clr3); pDC->TextOut(pt.x, pt.y, str); CRect rect3; rect3.left = pt.x + 15; rect3.top = pt.y + 20; rect3.right = rect1.right - (rect2.left - rect1.left); rect3.bottom = rect1.bottom - (rect2.left - rect1.left); pt = pt2; pt.x += pDC->GetTextExtent("\x81\x97\x81\x97\x81\x97\x81\x97").cx + 3; pt2 = pt; int x = rect1.right - (rect2.left - rect1.left); pDC->SelectObject(pen4); pDC->MoveTo(pt.x, pt.y + 14); pDC->LineTo(x, pt.y + 14); pDC->SelectObject(pen1); pDC->MoveTo(pt.x + 1, pt.y + 15); pDC->LineTo(x + 1, pt.y + 15); pt.y += 23; pDC->SelectObject(pen4); pDC->MoveTo(pt.x, pt.y + 14); pDC->LineTo(x, pt.y + 14); pDC->SelectObject(pen1); pDC->MoveTo(pt.x + 1, pt.y + 15); pDC->LineTo(x + 1, pt.y + 15); pt.y += 23; pDC->SelectObject(pen4); pDC->MoveTo(pt.x, pt.y + 14); pDC->LineTo(x, pt.y + 14); pDC->SelectObject(pen1); pDC->MoveTo(pt.x + 1, pt.y + 15); pDC->LineTo(x + 1, pt.y + 15); font.Detach(); font.CreateFont(-12, 0, 0, 0, FW_DONTCARE, false, false, false, SHIFTJIS_CHARSET, OUT_TT_PRECIS, CLIP_TT_ALWAYS, PROOF_QUALITY, DEFAULT_PITCH, "\x82\x6C\x82\x72 \x82\x6F\x83\x53\x83\x56\x83\x62\x83\x4E"); pDC->SelectObject(&font)->DeleteObject(); pDC->SetTextColor(clr3); pt = pt2; pt.x = x; str = *mPlugins[mSelectedPlugin].mStrC; pDC->TextOut(pt.x - pDC->GetTextExtent(str).cx, pt.y, str); pt.y += 23; str = *mPlugins[mSelectedPlugin].mStr10; pDC->TextOut(pt.x - pDC->GetTextExtent(str).cx, pt.y, str); pt.y += 23; str = *mPlugins[mSelectedPlugin].mStr14; pDC->TextOut(pt.x - pDC->GetTextExtent(str).cx, pt.y, str); pDC->DrawText(*mPlugins[mSelectedPlugin].mStr18, rect3, DT_WORDBREAK); pDC->RestoreDC(save); } /*virtual*/ BOOL T2WorldSelectDlg::OnT2DialogCommand(WPARAM inWParam, LPARAM inLParam) { BOOL result = true; WORD code = HIWORD(inWParam); WORD id = LOWORD(inWParam); if (id == kCmdOK && code == 0) { ShowWindow(SW_HIDE); mDocument->xUnkNameSelectWorld(GetSelectedPlugin()); DestroyWindow(); } else if (id == kCmdLeft && code == 0) { GoLeft(); } else if (id == kCmdRight && code == 0) { GoRight(); } else { result = T2Dialog::OnCommand(inWParam, inLParam); } return result; } void T2WorldSelectDlg::x432436(CDC *pDC) { #pragma var_order(pen1, pen2, save, rect) int save = pDC->SaveDC(); CPen pen1; pen1.CreatePen(PS_SOLID, 0, PALETTERGB(255, 255, 255)); CPen pen2; pen2.CreatePen(PS_SOLID, 0, PALETTERGB(133, 133, 133)); CRect rect; rect = mRect3; pDC->SelectObject(pen1); pDC->MoveTo(rect.right - 1, rect.top); pDC->LineTo(rect.left, rect.top); pDC->LineTo(rect.left, rect.bottom); pDC->SelectObject(pen2); pDC->MoveTo(rect.right - 1, rect.top + 1); pDC->LineTo(rect.right - 1, rect.bottom - 1); pDC->LineTo(rect.left, rect.bottom - 1); pDC->RestoreDC(save); }