gxFont *gxGraphics::loadFont( const string &f,int height,int flags ){ int bold=flags & gxFont::FONT_BOLD ? FW_BOLD : FW_REGULAR; int italic=flags & gxFont::FONT_ITALIC ? 1 : 0; int underline=flags & gxFont::FONT_UNDERLINE ? 1 : 0; int strikeout=0; string t; int n=f.find('.'); if( n!=string::npos ){ t=fullfilename(f); if( !font_res.count(t) && AddFontResource( t.c_str() ) ) font_res.insert( t ); t=filenamefile( f.substr(0,n) ); }else{ t=f; } //save and turn off font smoothing.... BOOL smoothing=FALSE; SystemParametersInfo( SPI_GETFONTSMOOTHING,0,&smoothing,0 ); SystemParametersInfo( SPI_SETFONTSMOOTHING,FALSE,0,0 ); HFONT hfont=CreateFont( height,0,0,0, bold,italic,underline,strikeout, ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE,t.c_str() ); if( !hfont ){ //restore font smoothing SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 ); return 0; } HDC hdc=CreateCompatibleDC( 0 ); HFONT pfont=(HFONT)SelectObject( hdc,hfont ); TEXTMETRIC tm={0}; if( !GetTextMetrics( hdc,&tm ) ){ SelectObject( hdc,pfont ); DeleteDC( hdc ); DeleteObject( hfont ); SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 ); return 0; } height=tm.tmHeight; int first=tm.tmFirstChar,last=tm.tmLastChar; int sz=last-first+1; int *offs=d_new int[sz]; int *widths=d_new int[sz]; int *as=d_new int[sz]; //calc size of canvas to hold font. int x=0,y=0,max_x=0; for( int k=0;k<sz;++k ){ char t=k+first; SIZE sz; GetTextExtentPoint32( hdc,&t,1,&sz ); int w=sz.cx; as[k]=0; ABC abc; if( GetCharABCWidths( hdc,t,t,&abc ) ){ if( abc.abcA<0 ){ as[k]=ceil(-abc.abcA); w+=as[k]; } if( abc.abcC<0 ) w+=ceil(-abc.abcC); } if( x && x+w>getWidth() ){ x=0;y+=height; } offs[k]=(x<<16)|y; widths[k]=w; x+=w;if( x>max_x ) max_x=x; } SelectObject( hdc,pfont ); DeleteDC( hdc ); int cw=max_x,ch=y+height; if( gxCanvas *c=createCanvas( cw,ch,0 ) ){ ddSurf *surf=c->getSurface(); HDC surf_hdc; if( surf->GetDC( &surf_hdc )>=0 ){ HFONT pfont=(HFONT)SelectObject( surf_hdc,hfont ); SetBkColor( surf_hdc,0x000000 ); SetTextColor( surf_hdc,0xffffff ); for( int k=0;k<sz;++k ){ int x=(offs[k]>>16)&0xffff,y=offs[k]&0xffff; char t=k+first; RECT rect={x,y,x+widths[k],y+height}; ExtTextOut( surf_hdc,x+as[k],y,ETO_CLIPPED,&rect,&t,1,0 ); } SelectObject( surf_hdc,pfont ); surf->ReleaseDC( surf_hdc ); DeleteObject( hfont ); delete[] as; c->backup(); gxFont *font=d_new gxFont( this,c,tm.tmMaxCharWidth,height,first,last+1,tm.tmDefaultChar,offs,widths ); font_set.insert( font ); //restore font smoothing SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 ); return font; }else{
int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs, bool mirrored) const { int i = 0; int glyph_pos = 0; if (mirrored) { #if defined(Q_WS_WINCE) { #else if (symbol) { for (; i < numChars; ++i, ++glyph_pos) { unsigned int uc = getChar(str, i, numChars); glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); if (!glyphs->glyphs[glyph_pos] && uc < 0x100) glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); } } else if (ttf) { for (; i < numChars; ++i, ++glyph_pos) { unsigned int uc = getChar(str, i, numChars); glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, QChar::mirroredChar(uc)); } } else { #endif wchar_t first = tm.tmFirstChar; wchar_t last = tm.tmLastChar; for (; i < numChars; ++i, ++glyph_pos) { uint ucs = QChar::mirroredChar(getChar(str, i, numChars)); if ( #ifdef Q_WS_WINCE tm.tmFirstChar > 60000 || // see line 375 #endif ucs >= first && ucs <= last) glyphs->glyphs[glyph_pos] = ucs; else glyphs->glyphs[glyph_pos] = 0; } } } else { #if defined(Q_WS_WINCE) { #else if (symbol) { for (; i < numChars; ++i, ++glyph_pos) { unsigned int uc = getChar(str, i, numChars); glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); if(!glyphs->glyphs[glyph_pos] && uc < 0x100) glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); } } else if (ttf) { for (; i < numChars; ++i, ++glyph_pos) { unsigned int uc = getChar(str, i, numChars); glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); } } else { #endif wchar_t first = tm.tmFirstChar; wchar_t last = tm.tmLastChar; for (; i < numChars; ++i, ++glyph_pos) { uint uc = getChar(str, i, numChars); if ( #ifdef Q_WS_WINCE tm.tmFirstChar > 60000 || // see comment in QFontEngineWin #endif uc >= first && uc <= last) glyphs->glyphs[glyph_pos] = uc; else glyphs->glyphs[glyph_pos] = 0; } } } glyphs->numGlyphs = glyph_pos; return glyph_pos; } QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont, LOGFONT lf) { //qDebug("regular windows font engine created: font='%s', size=%d", name, lf.lfHeight); _name = name; cmap = 0; cmapSize = 0; hfont = _hfont; logfont = lf; HDC hdc = shared_dc(); SelectObject(hdc, hfont); this->stockFont = stockFont; fontDef.pixelSize = -lf.lfHeight; lbearing = SHRT_MIN; rbearing = SHRT_MIN; synthesized_flags = -1; lineWidth = -1; x_height = -1; BOOL res = GetTextMetrics(hdc, &tm); fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH); if (!res) { qErrnoWarning("QFontEngineWin: GetTextMetrics failed"); ZeroMemory(&tm, sizeof(TEXTMETRIC)); } cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000; getCMap(); widthCache = 0; widthCacheSize = 0; designAdvances = 0; designAdvancesSize = 0; #ifndef Q_WS_WINCE if (!resolvedGetCharWidthI) resolveGetCharWidthI(); #endif }
BOOL WINAPI _export BLExtTextOut(HDC hDC, int x, int y, UINT fuOpt, const RECT FAR* lprc, LPCSTR lpStr, UINT cbLen, int FAR* lpDx) { POINT pt ; HWND hWDC ; HWND hWPT ; #ifdef _DEBUG DbgPrintf("NhWSrh.DLL BLExtTextOut Begin"); DbgPrintf("NhWSrh.DLL BLExtTextOut hDC: %d, x: %d, y: %d, fuOpt: %d, cbLen: %d", hDC, x, y, fuOpt, cbLen); #endif // restore the old textout. RestoreWinApi(&g_ExtTextOutHook); //Added by XGL, Nov 3rd, 1998 //We cannot get corret word with Explorer as background window //in Windows98, so this situation must be dealt with. pt.x = g_CurMousePos.x; pt.y = g_CurMousePos.y ; hWDC = WindowFromDC(hDC) ; hWPT = WindowFromPoint(pt) ; if (hWDC == NULL || hWPT == hWDC || IsParentOrSelf(hWPT, hWDC) || IsParentOrSelf(hWDC, hWPT)) { //Adding ends. XGL, Nov 3rd, 1998 if ((g_bAllowGetCurWord) && (!IsBadReadPtr(lpStr, cbLen)) && (cbLen > 0)) { g_nTextAlign = GetTextAlign(hDC); g_nExtra = GetTextCharacterExtra(hDC); GetCurrentPositionEx(hDC, &g_CurPos); GetTextMetrics(hDC, &g_tm); /////////////////////////////////////////////////////////////////////////// // Modify by Yan/Gang 1997/11/18 // 用於修改在计算 TA_CENTER 情况的失误。 g_dwDCOrg = 0; bRecAllRect = FALSE; GetStringRect(hDC, (LPSTR)lpStr, cbLen, x, y, &g_rcTotalRect, lpDx); bRecAllRect = TRUE; // End Modify /////////////////////////////////////////////////////////////////////////// if ((WindowFromDC != NULL)&&(WindowFromDC(hDC) == NULL)) { #ifdef _DEBUG DbgPrintf("NhWSrh.DLL BLTextOut WindowFromDC() == NULL"); DbgLPCSTR("NhWSrh.DLL BLTextOut: ", (LPSTR)lpStr, cbLen, TRUE); #endif // 赋零,用於避免MEMDC对串位置的影响· g_dwDCOrg = 0; AddToTextOutBuffer(hDC, (LPSTR)lpStr, cbLen, x, y, lpDx); } else { #ifdef _DEBUG DbgPrintf("NhWSrh.DLL BLTextOut WindowFromDC() != NULL"); DbgLPCSTR("NhWSrh.DLL BLTextOut: ", (LPSTR)lpStr, cbLen, TRUE); #endif g_dwDCOrg = GetDCOrg(hDC); GetCurMousePosWord(hDC, (LPSTR)lpStr, cbLen, x, y, lpDx); } } else { #ifdef _DEBUG DbgPrintf("NhWSrh.DLL BLExtTextOut ((!g_bAllowGetCurWord) || (IsBadReadPtr(lpStr, cbLen)) && (cbLen <= 0))"); if (!g_bAllowGetCurWord) { DbgPrintf("NhWSrh.DLL BLExtTextOut !g_bAllowGetCurWord"); } if (IsBadReadPtr(lpStr, cbLen)) { DbgPrintf("NhWSrh.DLL BLExtTextOut IsBadReadPtr()"); } if (cbLen <= 0) { DbgPrintf("NhWSrh.DLL BLExtTextOut cbLen <= 0"); } #endif } } // call old textout. ExtTextOut(hDC, x, y, fuOpt, lprc, lpStr, cbLen, lpDx); HookWinApi(&g_ExtTextOutHook, ONLYHOOK); #ifdef _DEBUG DbgPrintf("NhWSrh.DLL BLExtTextOut End"); #endif return (TRUE); }
void Update() { if(m_text==m_ss.str()){ return; } m_text=m_ss.str(); m_image->Clear(); BYTE *data=m_image->GetSample(); int pitch=m_image->GetWidth()*4; // フォントの生成 LOGFONT lf = {m_fontsize, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FIXED_PITCH | FF_MODERN, _T("MS 明朝")}; HFONT hFont=CreateFontIndirect(&lf); if(!(hFont)){ return; } // デバイスコンテキスト取得 // デバイスにフォントを持たせないとGetGlyphOutline関数はエラーとなる HDC hdc = GetDC(NULL); HFONT oldFont = (HFONT)SelectObject(hdc, hFont); std::vector<BYTE> gryph; int x_pos=0; int y_pos=0; int col_size=m_fontsize/2; for(auto c=m_text.begin(); c!=m_text.end(); ++c){ if(y_pos>=m_row*m_fontsize){ break; } if(*c==L'\n'){ y_pos+=m_fontsize+5; x_pos=0; continue; } if(x_pos+col_size>=m_col*col_size){ y_pos+=m_fontsize+5; x_pos=0; } // フォントビットマップ取得 TEXTMETRIC TM; GetTextMetrics( hdc, &TM ); GLYPHMETRICS GM; CONST MAT2 Mat = {{0,1},{0,0},{0,0},{0,1}}; DWORD size = GetGlyphOutline(hdc, *c, GGO_GRAY4_BITMAP, &GM, 0, NULL, &Mat); if(size>0){ gryph.resize(size); GetGlyphOutline(hdc, *c, GGO_GRAY4_BITMAP, &GM, gryph.size(), &gryph[0], &Mat); // フォント情報の書き込み // iOfs_x, iOfs_y : 書き出し位置(左上) // iBmp_w, iBmp_h : フォントビットマップの幅高 // Level : α値の段階 (GGO_GRAY4_BITMAPなので17段階) int iOfs_x = x_pos+GM.gmptGlyphOrigin.x; int iOfs_y = y_pos+TM.tmAscent - GM.gmptGlyphOrigin.y; int iBmp_w = GM.gmBlackBoxX + (4-(GM.gmBlackBoxX%4))%4; int iBmp_h = GM.gmBlackBoxY; int Level = 17; DWORD Alpha, Color; for(int y=iOfs_y; y<iOfs_y+iBmp_h; y++){ for(size_t x=iOfs_x; x<iOfs_x+GM.gmBlackBoxX; x++){ Alpha = (255 * gryph[x-iOfs_x + iBmp_w*(y-iOfs_y)]) / (Level-1); Color = 0x00ffffff | (Alpha<<24); memcpy((BYTE*)data + pitch*y + 4*x, &Color, sizeof(DWORD)); } } x_pos+=iBmp_w; } else{ x_pos+=col_size; } } // デバイスコンテキストとフォントハンドルの開放 SelectObject(hdc, oldFont); DeleteObject(hFont); ReleaseDC(NULL, hdc); }
extern "C" BOOL EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat) { // Don't print empty documents if (SendMessage(hwnd,SCI_GETLENGTH,0,0) == 0) { MsgBox(MBWARN,IDS_PRINT_EMPTY); return TRUE; } int startPos; int endPos; HDC hdc; RECT rectMargins; RECT rectPhysMargins; RECT rectSetup; POINT ptPage; POINT ptDpi; //RECT rectSetup; TEXTMETRIC tm; int headerLineHeight; HFONT fontHeader; int footerLineHeight; HFONT fontFooter; WCHAR dateString[256]; DOCINFO di = {sizeof(DOCINFO), 0, 0, 0, 0}; LONG lengthDoc; LONG lengthDocMax; LONG lengthPrinted; struct RangeToFormat frPrint; int pageNum; BOOL printPage; WCHAR pageString[32]; HPEN pen; HPEN penOld; PRINTDLG pdlg = { sizeof(PRINTDLG), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; pdlg.hwndOwner = GetParent(hwnd); pdlg.hInstance = g_hInstance; pdlg.Flags = PD_USEDEVMODECOPIES | PD_ALLPAGES | PD_RETURNDC; pdlg.nFromPage = 1; pdlg.nToPage = 1; pdlg.nMinPage = 1; pdlg.nMaxPage = 0xffffU; pdlg.nCopies = 1; pdlg.hDC = 0; pdlg.hDevMode = hDevMode; pdlg.hDevNames = hDevNames; startPos = SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0);; endPos = SendMessage(hwnd,SCI_GETSELECTIONEND,0,0); if (startPos == endPos) { pdlg.Flags |= PD_NOSELECTION; } else { pdlg.Flags |= PD_SELECTION; } if (0) { // Don't display dialog box, just use the default printer and options pdlg.Flags |= PD_RETURNDEFAULT; } if (!PrintDlg(&pdlg)) { return TRUE; // False means error... } hDevMode = pdlg.hDevMode; hDevNames = pdlg.hDevNames; hdc = pdlg.hDC; // Get printer resolution ptDpi.x = GetDeviceCaps(hdc, LOGPIXELSX); // dpi in X direction ptDpi.y = GetDeviceCaps(hdc, LOGPIXELSY); // dpi in Y direction // Start by getting the physical page size (in device units). ptPage.x = GetDeviceCaps(hdc, PHYSICALWIDTH); // device units ptPage.y = GetDeviceCaps(hdc, PHYSICALHEIGHT); // device units // Get the dimensions of the unprintable // part of the page (in device units). rectPhysMargins.left = GetDeviceCaps(hdc, PHYSICALOFFSETX); rectPhysMargins.top = GetDeviceCaps(hdc, PHYSICALOFFSETY); // To get the right and lower unprintable area, // we take the entire width and height of the paper and // subtract everything else. rectPhysMargins.right = ptPage.x // total paper width - GetDeviceCaps(hdc, HORZRES) // printable width - rectPhysMargins.left; // left unprintable margin rectPhysMargins.bottom = ptPage.y // total paper height - GetDeviceCaps(hdc, VERTRES) // printable height - rectPhysMargins.top; // right unprintable margin // At this point, rectPhysMargins contains the widths of the // unprintable regions on all four sides of the page in device units. // Take in account the page setup given by the user (if one value is not null) if (pagesetupMargin.left != 0 || pagesetupMargin.right != 0 || pagesetupMargin.top != 0 || pagesetupMargin.bottom != 0) { // Convert the hundredths of millimeters (HiMetric) or // thousandths of inches (HiEnglish) margin values // from the Page Setup dialog to device units. // (There are 2540 hundredths of a mm in an inch.) WCHAR localeInfo[3]; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE, localeInfo, 3); if (localeInfo[0] == L'0') { // Metric system. L'1' is US System rectSetup.left = MulDiv (pagesetupMargin.left, ptDpi.x, 2540); rectSetup.top = MulDiv (pagesetupMargin.top, ptDpi.y, 2540); rectSetup.right = MulDiv(pagesetupMargin.right, ptDpi.x, 2540); rectSetup.bottom = MulDiv(pagesetupMargin.bottom, ptDpi.y, 2540); } else { rectSetup.left = MulDiv(pagesetupMargin.left, ptDpi.x, 1000); rectSetup.top = MulDiv(pagesetupMargin.top, ptDpi.y, 1000); rectSetup.right = MulDiv(pagesetupMargin.right, ptDpi.x, 1000); rectSetup.bottom = MulDiv(pagesetupMargin.bottom, ptDpi.y, 1000); } // Dont reduce margins below the minimum printable area rectMargins.left = max(rectPhysMargins.left, rectSetup.left); rectMargins.top = max(rectPhysMargins.top, rectSetup.top); rectMargins.right = max(rectPhysMargins.right, rectSetup.right); rectMargins.bottom = max(rectPhysMargins.bottom, rectSetup.bottom); } else { rectMargins.left = rectPhysMargins.left; rectMargins.top = rectPhysMargins.top; rectMargins.right = rectPhysMargins.right; rectMargins.bottom = rectPhysMargins.bottom; } // rectMargins now contains the values used to shrink the printable // area of the page. // Convert device coordinates into logical coordinates DPtoLP(hdc, (LPPOINT)&rectMargins, 2); DPtoLP(hdc, (LPPOINT)&rectPhysMargins, 2); // Convert page size to logical units and we're done! DPtoLP(hdc, (LPPOINT) &ptPage, 1); headerLineHeight = MulDiv(8,ptDpi.y, 72); fontHeader = CreateFont(headerLineHeight, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0, L"Arial"); SelectObject(hdc, fontHeader); GetTextMetrics(hdc, &tm); headerLineHeight = tm.tmHeight + tm.tmExternalLeading; if (iPrintHeader == 3) headerLineHeight = 0; footerLineHeight = MulDiv(7,ptDpi.y, 72); fontFooter = CreateFont(footerLineHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 0, L"Arial"); SelectObject(hdc, fontFooter); GetTextMetrics(hdc, &tm); footerLineHeight = tm.tmHeight + tm.tmExternalLeading; if (iPrintFooter == 1) footerLineHeight = 0; di.lpszDocName = pszDocTitle; di.lpszOutput = 0; di.lpszDatatype = 0; di.fwType = 0; if (StartDoc(hdc, &di) < 0) { DeleteDC(hdc); if (fontHeader) DeleteObject(fontHeader); if (fontFooter) DeleteObject(fontFooter); return FALSE; } // Get current date... SYSTEMTIME st; GetLocalTime(&st); GetDateFormat(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&st,NULL,dateString,256); // Get current time... if (iPrintHeader == 0) { WCHAR timeString[128]; GetTimeFormat(LOCALE_USER_DEFAULT,TIME_NOSECONDS,&st,NULL,timeString,128); lstrcat(dateString,L" "); lstrcat(dateString,timeString); } // Set print color mode int printColorModes[5] = { SC_PRINT_NORMAL, SC_PRINT_INVERTLIGHT, SC_PRINT_BLACKONWHITE, SC_PRINT_COLOURONWHITE, SC_PRINT_COLOURONWHITEDEFAULTBG }; SendMessage(hwnd,SCI_SETPRINTCOLOURMODE,printColorModes[iPrintColor],0); // Set print zoom... SendMessage(hwnd,SCI_SETPRINTMAGNIFICATION,(WPARAM)iPrintZoom,0); lengthDoc = SendMessage(hwnd,SCI_GETLENGTH,0,0); lengthDocMax = lengthDoc; lengthPrinted = 0; // Requested to print selection if (pdlg.Flags & PD_SELECTION) { if (startPos > endPos) { lengthPrinted = endPos; lengthDoc = startPos; } else { lengthPrinted = startPos; lengthDoc = endPos; } if (lengthPrinted < 0) lengthPrinted = 0; if (lengthDoc > lengthDocMax) lengthDoc = lengthDocMax; } // We must substract the physical margins from the printable area frPrint.hdc = hdc; frPrint.hdcTarget = hdc; frPrint.rc.left = rectMargins.left - rectPhysMargins.left; frPrint.rc.top = rectMargins.top - rectPhysMargins.top; frPrint.rc.right = ptPage.x - rectMargins.right - rectPhysMargins.left; frPrint.rc.bottom = ptPage.y - rectMargins.bottom - rectPhysMargins.top; frPrint.rcPage.left = 0; frPrint.rcPage.top = 0; frPrint.rcPage.right = ptPage.x - rectPhysMargins.left - rectPhysMargins.right - 1; frPrint.rcPage.bottom = ptPage.y - rectPhysMargins.top - rectPhysMargins.bottom - 1; frPrint.rc.top += headerLineHeight + headerLineHeight / 2; frPrint.rc.bottom -= footerLineHeight + footerLineHeight / 2; // Print each page pageNum = 1; while (lengthPrinted < lengthDoc) { printPage = (!(pdlg.Flags & PD_PAGENUMS) || (pageNum >= pdlg.nFromPage) && (pageNum <= pdlg.nToPage)); wsprintf(pageString, pszPageFormat, pageNum); if (printPage) { // Show wait cursor... BeginWaitCursor(); // Display current page number in Statusbar StatusUpdatePrintPage(pageNum); StartPage(hdc); SetTextColor(hdc, RGB(0,0,0)); SetBkColor(hdc, RGB(255,255,255)); SelectObject(hdc, fontHeader); UINT ta = SetTextAlign(hdc, TA_BOTTOM); RECT rcw = {frPrint.rc.left, frPrint.rc.top - headerLineHeight - headerLineHeight / 2, frPrint.rc.right, frPrint.rc.top - headerLineHeight / 2}; rcw.bottom = rcw.top + headerLineHeight; if (iPrintHeader < 3) { ExtTextOut(hdc, frPrint.rc.left + 5, frPrint.rc.top - headerLineHeight / 2, /*ETO_OPAQUE*/0, &rcw, pszDocTitle, lstrlen(pszDocTitle), NULL); } // Print date in header if (iPrintHeader == 0 || iPrintHeader == 1) { SIZE sizeInfo; SelectObject(hdc,fontFooter); GetTextExtentPoint32(hdc,dateString,lstrlen(dateString),&sizeInfo); ExtTextOut(hdc, frPrint.rc.right - 5 - sizeInfo.cx, frPrint.rc.top - headerLineHeight / 2, /*ETO_OPAQUE*/0, &rcw, dateString, lstrlen(dateString), NULL); } if (iPrintHeader < 3) { SetTextAlign(hdc, ta); pen = CreatePen(0, 1, RGB(0,0,0)); penOld = (HPEN)SelectObject(hdc, pen); MoveToEx(hdc, frPrint.rc.left, frPrint.rc.top - headerLineHeight / 4, NULL); LineTo(hdc, frPrint.rc.right, frPrint.rc.top - headerLineHeight / 4); SelectObject(hdc, penOld); DeleteObject(pen); } } frPrint.chrg.cpMin = lengthPrinted; frPrint.chrg.cpMax = lengthDoc; lengthPrinted = SendMessage(hwnd,SCI_FORMATRANGE,printPage,(LPARAM)&frPrint); if (printPage) { SetTextColor(hdc, RGB(0,0,0)); SetBkColor(hdc, RGB(255,255,255)); SelectObject(hdc, fontFooter); UINT ta = SetTextAlign(hdc, TA_TOP); RECT rcw = {frPrint.rc.left, frPrint.rc.bottom + footerLineHeight / 2, frPrint.rc.right, frPrint.rc.bottom + footerLineHeight + footerLineHeight / 2}; if (iPrintFooter == 0) { SIZE sizeFooter; GetTextExtentPoint32(hdc,pageString,lstrlen(pageString),&sizeFooter); ExtTextOut(hdc, frPrint.rc.right - 5 - sizeFooter.cx, frPrint.rc.bottom + footerLineHeight / 2, /*ETO_OPAQUE*/0, &rcw, pageString, lstrlen(pageString), NULL); SetTextAlign(hdc, ta); pen = ::CreatePen(0, 1, RGB(0,0,0)); penOld = (HPEN)SelectObject(hdc, pen); SetBkColor(hdc, RGB(0,0,0)); MoveToEx(hdc, frPrint.rc.left, frPrint.rc.bottom + footerLineHeight / 4, NULL); LineTo(hdc, frPrint.rc.right, frPrint.rc.bottom + footerLineHeight / 4); SelectObject(hdc, penOld); DeleteObject(pen); } EndPage(hdc); } pageNum++; if ((pdlg.Flags & PD_PAGENUMS) && (pageNum > pdlg.nToPage)) break; } SendMessage(hwnd,SCI_FORMATRANGE, FALSE, 0); EndDoc(hdc); DeleteDC(hdc); if (fontHeader) DeleteObject(fontHeader); if (fontFooter) DeleteObject(fontFooter); // Reset Statusbar to default mode StatusSetSimple(hwndStatus,FALSE); // Remove wait cursor... EndWaitCursor(); return TRUE; }
int Wout::GetTextName() { GetTextMetrics(hDC, &textInfo); return textInfo. }
JNIEXPORT jlong JNICALL Java_sun_font_FileFontStrike__1getGlyphImageFromWindows (JNIEnv *env, jobject unused, jstring fontFamily, jint style, jint size, jint glyphCode, jboolean fm) { GLYPHMETRICS glyphMetrics; LOGFONTW lf; BITMAPINFO bmi; TEXTMETRIC textMetric; RECT rect; int bytesWidth, dibBytesWidth, extra, imageSize, dibImageSize; unsigned char* dibImage = NULL, *rowPtr, *pixelPtr, *dibPixPtr, *dibRowPtr; unsigned char r,g,b; unsigned char* igTable; GlyphInfo* glyphInfo = NULL; int nameLen; LPWSTR name; HFONT oldFont, hFont; MAT2 mat2; unsigned short width; unsigned short height; short advanceX; short advanceY; int topLeftX; int topLeftY; int err; int bmWidth, bmHeight; int x, y; HBITMAP hBitmap = NULL, hOrigBM; int gamma, orient; HWND hWnd = NULL; HDC hDesktopDC = NULL; HDC hMemoryDC = NULL; hWnd = GetDesktopWindow(); hDesktopDC = GetWindowDC(hWnd); if (hDesktopDC == NULL) { return (jlong)0; } if (GetDeviceCaps(hDesktopDC, BITSPIXEL) < 15) { FREE_AND_RETURN; } hMemoryDC = CreateCompatibleDC(hDesktopDC); if (hMemoryDC == NULL || fontFamily == NULL) { FREE_AND_RETURN; } err = SetMapMode(hMemoryDC, MM_TEXT); if (err == 0) { FREE_AND_RETURN; } memset(&lf, 0, sizeof(LOGFONTW)); lf.lfHeight = -size; lf.lfWeight = (style & 1) ? FW_BOLD : FW_NORMAL; lf.lfItalic = (style & 2) ? 0xff : 0; lf.lfCharSet = DEFAULT_CHARSET; lf.lfQuality = CLEARTYPE_QUALITY; lf.lfOutPrecision = OUT_TT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfPitchAndFamily = DEFAULT_PITCH; nameLen = (*env)->GetStringLength(env, fontFamily); name = (LPWSTR)alloca((nameLen+1)*2); if (name == NULL) { FREE_AND_RETURN; } (*env)->GetStringRegion(env, fontFamily, 0, nameLen, name); name[nameLen] = '\0'; if (nameLen < (sizeof(lf.lfFaceName) / sizeof(lf.lfFaceName[0]))) { wcscpy(lf.lfFaceName, name); } else { FREE_AND_RETURN; } hFont = CreateFontIndirectW(&lf); if (hFont == NULL) { FREE_AND_RETURN; } oldFont = SelectObject(hMemoryDC, hFont); memset(&textMetric, 0, sizeof(TEXTMETRIC)); err = GetTextMetrics(hMemoryDC, &textMetric); if (err == 0) { FREE_AND_RETURN; } memset(&glyphMetrics, 0, sizeof(GLYPHMETRICS)); memset(&mat2, 0, sizeof(MAT2)); mat2.eM11.value = 1; mat2.eM22.value = 1; err = GetGlyphOutline(hMemoryDC, glyphCode, GGO_METRICS|GGO_GLYPH_INDEX, &glyphMetrics, 0, NULL, &mat2); if (err == GDI_ERROR) { /* Probably no such glyph - ie the font wasn't the one we expected. */ FREE_AND_RETURN; } width = (unsigned short)glyphMetrics.gmBlackBoxX; height = (unsigned short)glyphMetrics.gmBlackBoxY; /* Don't handle "invisible" glyphs in this code */ if (width <= 0 || height == 0) { FREE_AND_RETURN; } advanceX = glyphMetrics.gmCellIncX; advanceY = glyphMetrics.gmCellIncY; topLeftX = glyphMetrics.gmptGlyphOrigin.x; topLeftY = glyphMetrics.gmptGlyphOrigin.y; /* GetGlyphOutline pre-dates cleartype and I'm not sure that it will * account for all pixels touched by the rendering. Need to widen, * and also adjust by one the x position at which it is rendered. * The extra pixels of width are used as follows : * One extra pixel at the left and the right will be needed to absorb * the pixels that will be touched by filtering by GDI to compensate * for colour fringing. * However there seem to be some cases where GDI renders two extra * pixels to the right, so we add one additional pixel to the right, * and in the code that copies this to the image cache we test for * the (rare) cases when this is touched, and if its not reduce the * stated image width for the blitting loops. * For fractional metrics : * One extra pixel at each end to account for sub-pixel positioning used * when fractional metrics is on in LCD mode. * The pixel at the left is needed so the blitting loop can index into * that a byte at a time to more accurately position the glyph. * The pixel at the right is needed so that when such indexing happens, * the blitting still can use the same width. * Consequently the width that is specified for the glyph is one less * than that of the actual image. * Note that in the FM case as a consequence we need to adjust the * position at which GDI renders, and the declared width of the glyph * See the if (fm) {} cases in the code. * For the non-FM case, we not only save 3 bytes per row, but this * prevents apparent glyph overlapping which affects the rendering * performance of accelerated pipelines since it adds additional * read-back requirements. */ width+=3; if (fm) { width+=1; } /* DIB scanline must end on a DWORD boundary. We specify 3 bytes per pixel, * so must round up as needed to a multiple of 4 bytes. */ dibBytesWidth = bytesWidth = width*3; extra = dibBytesWidth % 4; if (extra != 0) { dibBytesWidth += (4-extra); } /* The glyph cache image must be a multiple of 3 bytes wide. */ extra = bytesWidth % 3; if (extra != 0) { bytesWidth += (3-extra); } bmWidth = width; bmHeight = height; /* Must use desktop DC to create a bitmap of that depth */ hBitmap = CreateCompatibleBitmap(hDesktopDC, bmWidth, bmHeight); if (hBitmap == NULL) { FREE_AND_RETURN; } hOrigBM = (HBITMAP)SelectObject(hMemoryDC, hBitmap); /* Fill in black */ rect.left = 0; rect.top = 0; rect.right = bmWidth; rect.bottom = bmHeight; FillRect(hMemoryDC, (LPRECT)&rect, GetStockObject(BLACK_BRUSH)); /* Set text color to white, background to black. */ SetBkColor(hMemoryDC, RGB(0,0,0)); SetTextColor(hMemoryDC, RGB(255,255,255)); /* adjust rendering position */ x = -topLeftX+1; if (fm) { x += 1; } y = topLeftY - textMetric.tmAscent; err = ExtTextOutW(hMemoryDC, x, y, ETO_GLYPH_INDEX|ETO_OPAQUE, (LPRECT)&rect, (LPCWSTR)&glyphCode, 1, NULL); if (err == 0) { FREE_AND_RETURN; } /* Now get the image into a DIB. * MS docs for GetDIBits says the compatible bitmap must not be * selected into a DC, so restore the original first. */ SelectObject(hMemoryDC, hOrigBM); SelectObject(hMemoryDC, oldFont); DeleteObject(hFont); memset(&bmi, 0, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); bmi.bmiHeader.biWidth = width; bmi.bmiHeader.biHeight = -height; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 24; bmi.bmiHeader.biCompression = BI_RGB; dibImageSize = dibBytesWidth*height; dibImage = malloc(dibImageSize); if (dibImage == NULL) { FREE_AND_RETURN; } memset(dibImage, 0, dibImageSize); err = GetDIBits(hMemoryDC, hBitmap, 0, height, dibImage, &bmi, DIB_RGB_COLORS); if (err == 0) { /* GetDIBits failed. */ FREE_AND_RETURN; } err = SystemParametersInfo(SPI_GETFONTSMOOTHINGORIENTATION, 0, &orient, 0); if (err == 0) { FREE_AND_RETURN; } err = SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &gamma, 0); if (err == 0) { FREE_AND_RETURN; } igTable = getIGTable(gamma/10); if (igTable == NULL) { FREE_AND_RETURN; } /* Now copy glyph image into a GlyphInfo structure and return it. * NB the xadvance calculated here may be overwritten by the caller. * 1 is subtracted from the bitmap width to get the glyph width, since * that extra "1" was added as padding, so the sub-pixel positioning of * fractional metrics could index into it. */ imageSize = bytesWidth*height; glyphInfo = (GlyphInfo*)malloc(sizeof(GlyphInfo)+imageSize); if (glyphInfo == NULL) { FREE_AND_RETURN; } glyphInfo->cellInfo = NULL; glyphInfo->rowBytes = bytesWidth; glyphInfo->width = width; if (fm) { glyphInfo->width -= 1; // must subtract 1 } glyphInfo->height = height; glyphInfo->advanceX = advanceX; glyphInfo->advanceY = advanceY; glyphInfo->topLeftX = (float)(topLeftX-1); if (fm) { glyphInfo->topLeftX -= 1; } glyphInfo->topLeftY = (float)-topLeftY; glyphInfo->image = (unsigned char*)glyphInfo+sizeof(GlyphInfo); memset(glyphInfo->image, 0, imageSize); /* DIB 24bpp data is always stored in BGR order, but we usually * need this in RGB, so we can't just memcpy and need to swap B and R. * Also need to apply inverse gamma adjustment here. * We re-use the variable "extra" to see if the last pixel is touched * at all. If its not we can reduce the glyph image width. This comes * into play in some cases where GDI touches more pixels than accounted * for by increasing width by two pixels over the B&W image. Whilst * the bytes are in the cache, it doesn't affect rendering performance * of the hardware pipelines. */ extra = 0; if (fm) { extra = 1; // always need it. } dibRowPtr = dibImage; rowPtr = glyphInfo->image; for (y=0;y<height;y++) { pixelPtr = rowPtr; dibPixPtr = dibRowPtr; for (x=0;x<width;x++) { if (orient == FE_FONTSMOOTHINGORIENTATIONRGB) { b = *dibPixPtr++; g = *dibPixPtr++; r = *dibPixPtr++; } else { r = *dibPixPtr++; g = *dibPixPtr++; b = *dibPixPtr++; } *pixelPtr++ = igTable[r]; *pixelPtr++ = igTable[g]; *pixelPtr++ = igTable[b]; if (!fm && (x==(width-1)) && (r|g|b)) { extra = 1; } } dibRowPtr += dibBytesWidth; rowPtr += bytesWidth; } if (!extra) { glyphInfo->width -= 1; } free(dibImage); ReleaseDC(hWnd, hDesktopDC); DeleteObject(hMemoryDC); DeleteObject(hBitmap); return ptr_to_jlong(glyphInfo); }
static void InitChangeRegisterDialog(HWND hwnd,LPARAM lparam) { RegModifyData *data; char *name; unsigned len; mad_radix radix; mad_type_info mti; mad_type_info cmp; char s[255]; RECT p_rect; RECT c_rect; HWND field; int i; unsigned max_len; HDC dc; TEXTMETRIC tm; HWND cancel; SetWindowLong( hwnd, DWL_USER, (LONG)lparam); data = (RegModifyData *)lparam; len = MADRegFullName( data->curr_info, ".", NULL, 0 ); if( len > 0 ) { name = alloca( ( len + 1 ) * sizeof( char ) ); MADRegFullName( data->curr_info, ".", name, len ); SetWindowText( hwnd, name ); } else { SetWindowText( hwnd, "" ); } if( data->num_possible == 1 ) { field = GetDlgItem( hwnd, REG_EDIT_FIELD ); } else { field = GetDlgItem( hwnd, CH_REG_COMBO_LIST ); } SetMonoFont( field ); GetChildPos( hwnd, field, &c_rect); dc = GetDC( field ); GetTextMetrics( dc, &tm ); MADTypeInfo( data->th, &mti ); radix = MADTypePreferredRadix( data->th ); if( data->num_possible == 1 ) { if( data->maxv == 0 ) { len = 255; } else { len = data->maxv; } MADTypeToString( radix, &mti, data->curr_value, s, &len ); if( data->maxv == 0 ) { max_len = strlen( s ); } else { max_len = data->maxv; } SetDlgItemText(hwnd,REG_EDIT_FIELD,s); } else { MADTypeInfo( data->curr_info->type, &cmp ); max_len = 0; for( i = 0; i < data->num_possible; i++ ) { if( data->m_list[i].name == MAD_MSTR_NIL ) { len = sizeof( s ); MADTypeToString( radix, &mti, data->m_list[i].data, s, &len ); } else { MADCli( String )( data->m_list[i].name, s, sizeof( s ) ); } if( max_len < strlen( s ) ) max_len = strlen( s ); SendDlgItemMessage( hwnd, CH_REG_COMBO_LIST, CB_ADDSTRING, 0, (LPARAM)s ); if( memcmp( data->curr_value, data->m_list[i].data, BITS2BYTES( cmp.b.bits ) ) == 0 ) { SendDlgItemMessage( hwnd, CH_REG_COMBO_LIST, CB_SETCURSEL, (WPARAM)i, 0 ); } } c_rect.bottom += SendMessage( field, CB_GETITEMHEIGHT, 0, 0 ) * (i + 1); } max_len *= tm.tmMaxCharWidth; if( max_len > c_rect.right ) { max_len -= max_len%2; GetWindowRect( hwnd, &p_rect ); p_rect.right -= p_rect.left; p_rect.bottom -= p_rect.top; p_rect.left -= ( max_len - c_rect.right )/2; p_rect.right += ( max_len - c_rect.right ); MoveWindow( hwnd, p_rect.left, p_rect.top, p_rect.right, p_rect.bottom, FALSE ); cancel = GetDlgItem( hwnd, IDCANCEL ); GetChildPos( hwnd, cancel, &p_rect ); p_rect.left += ( max_len - c_rect.right ); MoveWindow( cancel, p_rect.left, p_rect.top, p_rect.right, p_rect.bottom, FALSE ); c_rect.right = max_len; } ReleaseDC( field, dc ); MoveWindow( field, c_rect.left, c_rect.top, c_rect.right, c_rect.bottom, FALSE ); }
int gui_mch_dialog( int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd) { FARPROC dp; LPWORD p, pnumitems; int numButtons; int *buttonWidths, *buttonPositions; int buttonYpos; int nchar, i; DWORD lStyle; int dlgwidth = 0; int dlgheight; int editboxheight; int horizWidth; int msgheight; char_u *pstart; char_u *pend; char_u *tbuffer; RECT rect; HWND hwnd; HDC hdc; HFONT oldFont; TEXTMETRIC fontInfo; int fontHeight; int textWidth, minButtonWidth, messageWidth; int maxDialogWidth; int vertical; int dlgPaddingX; int dlgPaddingY; HGLOBAL hglbDlgTemp; #ifndef NO_CONSOLE /* Don't output anything in silent mode ("ex -s") */ if (silent_mode) return dfltbutton; /* return default option */ #endif /* If there is no window yet, open it. */ if (s_hwnd == NULL && gui_mch_init() == FAIL) return dfltbutton; if ((type < 0) || (type > VIM_LAST_TYPE)) type = 0; /* allocate some memory for dialog template */ /* TODO should compute this really*/ hglbDlgTemp = GlobalAlloc(GHND, DLG_ALLOC_SIZE); if (hglbDlgTemp == NULL) return -1; p = (LPWORD) GlobalLock(hglbDlgTemp); if (p == NULL) return -1; /* * make a copy of 'buttons' to fiddle with it. compiler grizzles because * vim_strsave() doesn't take a const arg (why not?), so cast away the * const. */ tbuffer = vim_strsave(buttons); if (tbuffer == NULL) return -1; --dfltbutton; /* Change from one-based to zero-based */ /* Count buttons */ numButtons = 1; for (i = 0; tbuffer[i] != '\0'; i++) { if (tbuffer[i] == DLG_BUTTON_SEP) numButtons++; } if (dfltbutton >= numButtons) dfltbutton = 0; /* Allocate array to hold the width of each button */ buttonWidths = (int *) lalloc(numButtons * sizeof(int), TRUE); if (buttonWidths == NULL) return -1; /* Allocate array to hold the X position of each button */ buttonPositions = (int *) lalloc(numButtons * sizeof(int), TRUE); if (buttonPositions == NULL) return -1; /* * Calculate how big the dialog must be. */ hwnd = GetDesktopWindow(); hdc = GetWindowDC(hwnd); oldFont = SelectFont(hdc, GetStockObject(SYSTEM_FONT)); dlgPaddingX = DLG_OLD_STYLE_PADDING_X; dlgPaddingY = DLG_OLD_STYLE_PADDING_Y; GetTextMetrics(hdc, &fontInfo); fontHeight = fontInfo.tmHeight; /* Minimum width for horizontal button */ minButtonWidth = GetTextWidth(hdc, "Cancel", 6); /* Maximum width of a dialog, if possible */ GetWindowRect(s_hwnd, &rect); maxDialogWidth = rect.right - rect.left - GetSystemMetrics(SM_CXFRAME) * 2; if (maxDialogWidth < DLG_MIN_MAX_WIDTH) maxDialogWidth = DLG_MIN_MAX_WIDTH; /* Set dlgwidth to width of message */ pstart = message; messageWidth = 0; msgheight = 0; do { pend = vim_strchr(pstart, DLG_BUTTON_SEP); if (pend == NULL) pend = pstart + STRLEN(pstart); /* Last line of message. */ msgheight += fontHeight; textWidth = GetTextWidth(hdc, pstart, pend - pstart); if (textWidth > messageWidth) messageWidth = textWidth; pstart = pend + 1; } while (*pend != NUL); dlgwidth = messageWidth; /* Add width of icon to dlgwidth, and some space */ dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX; if (msgheight < DLG_ICON_HEIGHT) msgheight = DLG_ICON_HEIGHT; /* * Check button names. A long one will make the dialog wider. */ vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL); if (!vertical) { // Place buttons horizontally if they fit. horizWidth = dlgPaddingX; pstart = tbuffer; i = 0; do { pend = vim_strchr(pstart, DLG_BUTTON_SEP); if (pend == NULL) pend = pstart + STRLEN(pstart); // Last button name. textWidth = GetTextWidth(hdc, pstart, pend - pstart); if (textWidth < minButtonWidth) textWidth = minButtonWidth; textWidth += dlgPaddingX; /* Padding within button */ buttonWidths[i] = textWidth; buttonPositions[i++] = horizWidth; horizWidth += textWidth + dlgPaddingX; /* Pad between buttons */ pstart = pend + 1; } while (*pend != NUL); if (horizWidth > maxDialogWidth) vertical = TRUE; // Too wide to fit on the screen. else if (horizWidth > dlgwidth) dlgwidth = horizWidth; } if (vertical) { // Stack buttons vertically. pstart = tbuffer; do { pend = vim_strchr(pstart, DLG_BUTTON_SEP); if (pend == NULL) pend = pstart + STRLEN(pstart); // Last button name. textWidth = GetTextWidth(hdc, pstart, pend - pstart); textWidth += dlgPaddingX; /* Padding within button */ textWidth += DLG_VERT_PADDING_X * 2; /* Padding around button */ if (textWidth > dlgwidth) dlgwidth = textWidth; pstart = pend + 1; } while (*pend != NUL); } if (dlgwidth < DLG_MIN_WIDTH) dlgwidth = DLG_MIN_WIDTH; /* Don't allow a really thin dialog!*/ /* start to fill in the dlgtemplate information. addressing by WORDs */ lStyle = DS_MODALFRAME | WS_CAPTION | WS_VISIBLE ; add_long(lStyle); pnumitems = p; /*save where the number of items must be stored*/ add_byte(0); // NumberOfItems(will change later) add_word(10); // x add_word(10); // y add_word(PixelToDialogX(dlgwidth)); // Dialog height. if (vertical) dlgheight = msgheight + 2 * dlgPaddingY + DLG_VERT_PADDING_Y + 2 * fontHeight * numButtons; else dlgheight = msgheight + 3 * dlgPaddingY + 2 * fontHeight; // Dialog needs to be taller if contains an edit box. editboxheight = fontHeight + dlgPaddingY + 4 * DLG_VERT_PADDING_Y; if (textfield != NULL) dlgheight += editboxheight; add_word(PixelToDialogY(dlgheight)); add_byte(0); //menu add_byte(0); //class /* copy the title of the dialog */ add_string(title ? title : ("Vim"VIM_VERSION_MEDIUM)); buttonYpos = msgheight + 2 * dlgPaddingY; if (textfield != NULL) buttonYpos += editboxheight; pstart = tbuffer; //dflt_text horizWidth = (dlgwidth - horizWidth) / 2; /* Now it's X offset */ for (i = 0; i < numButtons; i++) { /* get end of this button. */ for ( pend = pstart; *pend && (*pend != DLG_BUTTON_SEP); pend++) ; if (*pend) *pend = '\0'; /* * NOTE: * setting the BS_DEFPUSHBUTTON style doesn't work because Windows sets * the focus to the first tab-able button and in so doing makes that * the default!! Grrr. Workaround: Make the default button the only * one with WS_TABSTOP style. Means user can't tab between buttons, but * he/she can use arrow keys. * * NOTE (Thore): Setting BS_DEFPUSHBUTTON works fine when it's the * first one, so I changed the correct button to be this style. This * is necessary because when an edit box is added, we need a button to * be default. The edit box will be the default control, and when the * user presses enter from the edit box we want the default button to * be pressed. */ if (vertical) { p = add_dialog_element(p, ((i == dfltbutton || dfltbutton < 0) && textfield != NULL ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP, PixelToDialogX(DLG_VERT_PADDING_X), PixelToDialogY(buttonYpos /* TBK */ + 2 * fontHeight * i), PixelToDialogX(dlgwidth - 2 * DLG_VERT_PADDING_X), (WORD)(PixelToDialogY(2 * fontHeight) - 1), (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart); } else { p = add_dialog_element(p, ((i == dfltbutton || dfltbutton < 0) && textfield != NULL ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP, PixelToDialogX(horizWidth + buttonPositions[i]), PixelToDialogY(buttonYpos), /* TBK */ PixelToDialogX(buttonWidths[i]), (WORD)(PixelToDialogY(2 * fontHeight) - 1), (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart); } pstart = pend + 1; /*next button*/ } *pnumitems += numButtons; /* Vim icon */ p = add_dialog_element(p, SS_ICON, PixelToDialogX(dlgPaddingX), PixelToDialogY(dlgPaddingY), PixelToDialogX(DLG_ICON_WIDTH), PixelToDialogY(DLG_ICON_HEIGHT), DLG_NONBUTTON_CONTROL + 0, (BYTE)0x82, &dlg_icons[type]); /* Dialog message */ p = add_dialog_element(p, SS_LEFT, PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH), PixelToDialogY(dlgPaddingY), (WORD)(PixelToDialogX(messageWidth) + 1), PixelToDialogY(msgheight), DLG_NONBUTTON_CONTROL + 1, (BYTE)0x82, message); /* Edit box */ if (textfield != NULL) { p = add_dialog_element(p, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP | WS_BORDER, PixelToDialogX(2 * dlgPaddingX), PixelToDialogY(2 * dlgPaddingY + msgheight), PixelToDialogX(dlgwidth - 4 * dlgPaddingX), PixelToDialogY(fontHeight + dlgPaddingY), DLG_NONBUTTON_CONTROL + 2, (BYTE)0x81, textfield); *pnumitems += 1; } *pnumitems += 2; SelectFont(hdc, oldFont); ReleaseDC(hwnd, hdc); dp = MakeProcInstance((FARPROC)dialog_callback, s_hinst); /* Let the dialog_callback() function know which button to make default * If we have an edit box, make that the default. We also need to tell * dialog_callback() if this dialog contains an edit box or not. We do * this by setting s_textfield if it does. */ if (textfield != NULL) { dialog_default_button = DLG_NONBUTTON_CONTROL + 2; s_textfield = textfield; } else { dialog_default_button = IDCANCEL + 1 + dfltbutton; s_textfield = NULL; } /*show the dialog box modally and get a return value*/ nchar = DialogBoxIndirect( s_hinst, (HGLOBAL) hglbDlgTemp, s_hwnd, (DLGPROC)dp); FreeProcInstance( dp ); GlobalUnlock(hglbDlgTemp); GlobalFree(hglbDlgTemp); vim_free(tbuffer); vim_free(buttonWidths); vim_free(buttonPositions); return nchar; }
LRESULT CALLBACK LConProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { HWND view; HDC hdc; HBRUSH hbr; HGDIOBJ oldfont; RECT rect; int titlelen; SIZE size; LOGFONT lf; TEXTMETRIC tm; HINSTANCE inst = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_HINSTANCE); DRAWITEMSTRUCT *drawitem; CHARFORMAT2W format; switch (msg) { case WM_CREATE: // Create game title static control memset (&lf, 0, sizeof(lf)); hdc = GetDC (hWnd); lf.lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72); lf.lfCharSet = ANSI_CHARSET; lf.lfWeight = FW_BOLD; lf.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN; strcpy (lf.lfFaceName, "Trebuchet MS"); GameTitleFont = CreateFontIndirect (&lf); oldfont = SelectObject (hdc, GetStockObject (DEFAULT_GUI_FONT)); GetTextMetrics (hdc, &tm); DefaultGUIFontHeight = tm.tmHeight; if (GameTitleFont == NULL) { GameTitleFontHeight = DefaultGUIFontHeight; } else { SelectObject (hdc, GameTitleFont); GetTextMetrics (hdc, &tm); GameTitleFontHeight = tm.tmHeight; } SelectObject (hdc, oldfont); // Create log read-only edit control view = CreateWindowEx (WS_EX_NOPARENTNOTIFY, "RichEdit20W", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | WS_CLIPSIBLINGS, 0, 0, 0, 0, hWnd, NULL, inst, NULL); HRESULT hr; hr = GetLastError(); if (view == NULL) { ReleaseDC (hWnd, hdc); return -1; } SendMessage (view, EM_SETREADONLY, TRUE, 0); SendMessage (view, EM_EXLIMITTEXT, 0, 0x7FFFFFFE); SendMessage (view, EM_SETBKGNDCOLOR, 0, RGB(70,70,70)); // Setup default font for the log. //SendMessage (view, WM_SETFONT, (WPARAM)GetStockObject (DEFAULT_GUI_FONT), FALSE); format.cbSize = sizeof(format); format.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_CHARSET; format.dwEffects = 0; format.yHeight = 200; format.crTextColor = RGB(223,223,223); format.bCharSet = ANSI_CHARSET; format.bPitchAndFamily = FF_SWISS | VARIABLE_PITCH; wcscpy(format.szFaceName, L"DejaVu Sans"); // At least I have it. :p SendMessageW(view, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&format); ConWindow = view; ReleaseDC (hWnd, hdc); view = CreateWindowEx (WS_EX_NOPARENTNOTIFY, "STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, hWnd, NULL, inst, NULL); if (view == NULL) { return -1; } SetWindowLong (view, GWL_ID, IDC_STATIC_TITLE); GameTitleWindow = view; return 0; case WM_SIZE: if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW) { LayoutMainWindow (hWnd, ErrorPane); } return 0; case WM_DRAWITEM: // Draw title banner. if (wParam == IDC_STATIC_TITLE && DoomStartupInfo.Name.IsNotEmpty()) { const PalEntry *c; // Draw the game title strip at the top of the window. drawitem = (LPDRAWITEMSTRUCT)lParam; // Draw the background. rect = drawitem->rcItem; rect.bottom -= 1; c = (const PalEntry *)&DoomStartupInfo.BkColor; hbr = CreateSolidBrush (RGB(c->r,c->g,c->b)); FillRect (drawitem->hDC, &drawitem->rcItem, hbr); DeleteObject (hbr); // Calculate width of the title string. SetTextAlign (drawitem->hDC, TA_TOP); oldfont = SelectObject (drawitem->hDC, GameTitleFont != NULL ? GameTitleFont : (HFONT)GetStockObject (DEFAULT_GUI_FONT)); titlelen = (int)DoomStartupInfo.Name.Len(); GetTextExtentPoint32 (drawitem->hDC, DoomStartupInfo.Name, titlelen, &size); // Draw the title. c = (const PalEntry *)&DoomStartupInfo.FgColor; SetTextColor (drawitem->hDC, RGB(c->r,c->g,c->b)); SetBkMode (drawitem->hDC, TRANSPARENT); TextOut (drawitem->hDC, rect.left + (rect.right - rect.left - size.cx) / 2, 2, DoomStartupInfo.Name, titlelen); SelectObject (drawitem->hDC, oldfont); return TRUE; } // Draw startup screen else if (wParam == IDC_STATIC_STARTUP) { if (StartupScreen != NULL) { drawitem = (LPDRAWITEMSTRUCT)lParam; rect = drawitem->rcItem; // Windows expects DIBs to be bottom-up but ours is top-down, // so flip it vertically while drawing it. StretchDIBits (drawitem->hDC, rect.left, rect.bottom - 1, rect.right - rect.left, rect.top - rect.bottom, 0, 0, StartupBitmap->bmiHeader.biWidth, StartupBitmap->bmiHeader.biHeight, ST_Util_BitsForBitmap(StartupBitmap), StartupBitmap, DIB_RGB_COLORS, SRCCOPY); // If the title banner is gone, then this is an ENDOOM screen, so draw a short prompt // where the command prompt would have been in DOS. if (GameTitleWindow == NULL) { static const char QuitText[] = "Press any key or click anywhere in the window to quit."; SetTextColor (drawitem->hDC, RGB(240,240,240)); SetBkMode (drawitem->hDC, TRANSPARENT); oldfont = SelectObject (drawitem->hDC, (HFONT)GetStockObject (DEFAULT_GUI_FONT)); TextOut (drawitem->hDC, 3, drawitem->rcItem.bottom - DefaultGUIFontHeight - 3, QuitText, countof(QuitText)-1); SelectObject (drawitem->hDC, oldfont); } return TRUE; } } // Draw stop icon. else if (wParam == IDC_ICONPIC) { HICON icon; POINTL char_pos; drawitem = (LPDRAWITEMSTRUCT)lParam; // This background color should match the edit control's. hbr = CreateSolidBrush (RGB(70,70,70)); FillRect (drawitem->hDC, &drawitem->rcItem, hbr); DeleteObject (hbr); // Draw the icon aligned with the first line of error text. SendMessage (ConWindow, EM_POSFROMCHAR, (WPARAM)&char_pos, ErrorIconChar); icon = (HICON)LoadImage (0, IDI_ERROR, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); DrawIcon (drawitem->hDC, 6, char_pos.y, icon); return TRUE; } return FALSE; case WM_COMMAND: if (ErrorIcon != NULL && (HWND)lParam == ConWindow && HIWORD(wParam) == EN_UPDATE) { // Be sure to redraw the error icon if the edit control changes. InvalidateRect (ErrorIcon, NULL, TRUE); return 0; } break; case WM_CLOSE: PostQuitMessage (0); break; case WM_DESTROY: if (GameTitleFont != NULL) { DeleteObject (GameTitleFont); } break; } return DefWindowProc (hWnd, msg, wParam, lParam); }
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxClientMax, cyClientMax, cxClient, cyClient, cxChar, cyChar ; static int cLinesMax, cLines ; static PMSG pmsg ; static RECT rectScroll ; static TCHAR szTop[] = TEXT ("Message Key Char ") TEXT ("Repeat Scan Ext ALT Prev Tran") ; static TCHAR szUnd[] = TEXT ("_______ ___ ____ ") TEXT ("______ ____ ___ ___ ____ ____") ; static TCHAR * szFormat[2] = { TEXT ("%-13s %3d %-15s%c%6u %4d %3s %3s %4s %4s"), TEXT ("%-13s 0x%04X%1s%c %6u %4d %3s %3s %4s %4s") } ; static TCHAR * szYes = TEXT ("Yes") ; static TCHAR * szNo = TEXT ("No") ; static TCHAR * szDown = TEXT ("Down") ; static TCHAR * szUp = TEXT ("Up") ; static TCHAR * szMessage [] = { TEXT ("WM_KEYDOWN"), TEXT ("WM_KEYUP"), TEXT ("WM_CHAR"), TEXT ("WM_DEADCHAR"), TEXT ("WM_SYSKEYDOWN"),TEXT ("WM_SYSKEYUP"), TEXT ("WM_SYSCHAR"), TEXT ("WM_SYSDEADCHAR") } ; HDC hdc ; int i, iType ; PAINTSTRUCT ps ; TCHAR szBuffer[128], szKeyName [32] ; TEXTMETRIC tm ; switch (message) { case WM_CREATE: case WM_DISPLAYCHANGE: // Get maximum size of client area cxClientMax = GetSystemMetrics (SM_CXMAXIMIZED) ; cyClientMax = GetSystemMetrics (SM_CYMAXIMIZED) ; // Get character size for fixed-pitch font hdc = GetDC (hwnd) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; GetTextMetrics (hdc, &tm) ; cxChar = tm.tmAveCharWidth ; cyChar = tm.tmHeight ; ReleaseDC (hwnd, hdc) ; // Allocate memory for display lines if (pmsg) free (pmsg) ; cLinesMax = cyClientMax / cyChar ; pmsg = malloc (cLinesMax * sizeof (MSG)) ; cLines = 0 ; // fall through case WM_SIZE: if (message == WM_SIZE) { cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; } // Calculate scrolling rectangle rectScroll.left = 0 ; rectScroll.right = cxClient ; rectScroll.top = cyChar ; rectScroll.bottom = cyChar * (cyClient / cyChar) ; InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; case WM_KEYDOWN: case WM_KEYUP: case WM_CHAR: case WM_DEADCHAR: case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_SYSCHAR: case WM_SYSDEADCHAR: // Rearrange storage array for (i = cLinesMax - 1 ; i > 0 ; i--) { pmsg[i] = pmsg[i - 1] ; } // Store new message pmsg[0].hwnd = hwnd ; pmsg[0].message = message ; pmsg[0].wParam = wParam ; pmsg[0].lParam = lParam ; cLines = min (cLines + 1, cLinesMax) ; // Scroll up the display ScrollWindow (hwnd, 0, -cyChar, &rectScroll, &rectScroll) ; break ; // i.e., call DefWindowProc so Sys messages work case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; SetBkMode (hdc, TRANSPARENT) ; TextOut (hdc, 0, 0, szTop, lstrlen (szTop)) ; TextOut (hdc, 0, 0, szUnd, lstrlen (szUnd)) ; for (i = 0 ; i < min (cLines, cyClient / cyChar - 1) ; i++) { iType = pmsg[i].message == WM_CHAR || pmsg[i].message == WM_SYSCHAR || pmsg[i].message == WM_DEADCHAR || pmsg[i].message == WM_SYSDEADCHAR ; GetKeyNameText (pmsg[i].lParam, szKeyName, sizeof (szKeyName) / sizeof (TCHAR)) ; TextOut (hdc, 0, (cyClient / cyChar - 1 - i) * cyChar, szBuffer, wsprintf (szBuffer, szFormat [iType], szMessage [pmsg[i].message - WM_KEYFIRST], pmsg[i].wParam, (PTSTR) (iType ? TEXT (" ") : szKeyName), (TCHAR) (iType ? pmsg[i].wParam : ' '), LOWORD (pmsg[i].lParam), HIWORD (pmsg[i].lParam) & 0xFF, 0x01000000 & pmsg[i].lParam ? szYes : szNo, 0x20000000 & pmsg[i].lParam ? szYes : szNo, 0x40000000 & pmsg[i].lParam ? szDown : szUp, 0x80000000 & pmsg[i].lParam ? szUp : szDown)) ; } EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }
long FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT wParam, LONG lParam) { static short cxChar, cxCaps, cyChar, cyClient, nVscrollPos ; char szBuffer[10] ; HDC hdc ; short i, y ; PAINTSTRUCT ps ; TEXTMETRIC tm ; switch (message) { case WM_CREATE: hdc = GetDC (hwnd) ; GetTextMetrics (hdc, &tm) ; cxChar = tm.tmAveCharWidth ; cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ; cyChar = tm.tmHeight + tm.tmExternalLeading ; ReleaseDC (hwnd, hdc) ; SetScrollRange (hwnd, SB_VERT, 0, NUMLINES, FALSE) ; SetScrollPos (hwnd, SB_VERT, nVscrollPos, TRUE) ; return 0 ; case WM_SIZE: cyClient = HIWORD (lParam) ; return 0 ; case WM_VSCROLL: switch (wParam) { case SB_LINEUP: nVscrollPos -= 1 ; break ; case SB_LINEDOWN: nVscrollPos += 1 ; break ; case SB_PAGEUP: nVscrollPos -= cyClient / cyChar ; break ; case SB_PAGEDOWN: nVscrollPos += cyClient / cyChar ; break ; case SB_THUMBPOSITION: nVscrollPos = LOWORD (lParam) ; break ; default: break ; } nVscrollPos = max (0, min (nVscrollPos, NUMLINES)) ; if (nVscrollPos != GetScrollPos (hwnd, SB_VERT)) { SetScrollPos (hwnd, SB_VERT, nVscrollPos, TRUE) ; InvalidateRect (hwnd, NULL, TRUE) ; } return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; for (i = 0 ; i < NUMLINES ; i++) { y = cyChar * (1 - nVscrollPos + i) ; TextOut (hdc, cxChar, y, sysmetrics[i].szLabel, lstrlen (sysmetrics[i].szLabel)) ; TextOut (hdc, cxChar + 22 * cxCaps, y, sysmetrics[i].szDesc, lstrlen (sysmetrics[i].szDesc)) ; SetTextAlign (hdc, TA_RIGHT | TA_TOP) ; TextOut (hdc, cxChar + 22 * cxCaps + 40 * cxChar, y, szBuffer, wsprintf (szBuffer, "%5d", GetSystemMetrics (sysmetrics[i].nIndex))) ; SetTextAlign (hdc, TA_LEFT | TA_TOP) ; } EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }
LONG FAR PASCAL MainMessageHandler(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) { HDC hDC; /* handle for the display device */ PAINTSTRUCT ps; /* holds PAINT information */ TEXTMETRIC tm; /* holds TEXT information */ static unsigned short *ADValues; /* Win32 pointer */ static HGLOBAL MemHandle32; static short CurStatus; static HRGN hRgn; /* Rectangle region Handles */ static int CharWidth, CharHeight; static HGLOBAL MemHandle; int x, y, i; long Count, Rate; char OutString[80], *str; float Voltage; unsigned short CurValue; switch (Message) /* Windows Message Loop */ { case WM_CREATE: hDC = GetDC(hWndMain); /* Get the device context for window */ GetTextMetrics(hDC, &tm); /* From context, get size of font */ CharWidth = tm.tmAveCharWidth; CharHeight = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hWndMain, hDC); hRgn = CreateRectRgn(0,0, CharWidth*30, CharHeight*20); /* Allocate a Windows buffer */ MemHandle = cbWinBufAlloc ((long)BUF_SIZE); /* WIN32: This code is added to be able access more than */ /* 32K words of data. */ /* WIN32: allocate a local WIN32 buffer to hold A/D Data */ MemHandle32 = GlobalAlloc(GMEM_FIXED | GMEM_DDESHARE, BUF_SIZE *sizeof(short)); /* Get a 32-bit pointer to the WIN32 buffer */ ADValues = (unsigned short *)GlobalLock(MemHandle32); /* Start up A/D scan */ Count = BUF_SIZE; Rate = BUF_SIZE / NUM_SECS; cbAInScan (BOARD_NUM, 0, 0, Count, &Rate, ADRANGE, MemHandle, CONVERTDATA); break; case WM_PAINT: /* Repaint client area of window */ hDC = BeginPaint(hWndMain, &ps); x = CharWidth * 2; /* Position cursor within window */ y = CharHeight; /* One line down and 2 chars in */ str = " A/D Info"; /* Print title */ TextOut(hDC, x, y, str, strlen (str)); Count = BUF_SIZE; /* Copy Data from memory to 32-bit memory buffer */ cbWinBufToArray( MemHandle, &ADValues[0], 0, Count ); for (i=0;i<=4;i++) { CurValue = ADValues[i]; y += CharHeight*2; /* Print raw data value */ sprintf (OutString,"Raw A/D value(%d) = %u ", i, CurValue); TextOut(hDC, x, y, OutString, strlen (OutString)); y += CharHeight; /* Convert raw A/D to volts and print */ cbToEngUnits(BOARD_NUM,ADRANGE,CurValue,&Voltage); sprintf (OutString,"Voltage = %.2f ", Voltage); TextOut(hDC, x, y, OutString, strlen (OutString)); } SetTextAlign(hDC, TA_LEFT | TA_TOP); EndPaint(hWndMain, &ps); break; case WM_CLOSE: /* Close the window */ DestroyWindow(hWnd); if (hWnd == hWndMain) PostQuitMessage(0); /* Send message to Quit application */ if (MemHandle) cbWinBufFree (MemHandle); /* Free allocated memory */ if ( MemHandle32 ) GlobalFree( MemHandle32 ); break; default: return (DefWindowProc(hWnd, Message, wParam, lParam)); } return (0l); }
/* initialize the process. Reads the init files to get the appropriate * information. */ BOOL InitInstance( HANDLE hInstance, int nCmdShow) { HWND hWnd; HDC hDC; TEXTMETRIC textmetric; INT nLineHeight; long code, cnt; char *reason; /* remember this, since it is a useful thing for some of the Windows * calls */ main_inst = hInstance; /* create our window */ hWnd = CreateWindow( "AFSDWinClass", "AFSD", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); if (!hWnd) return (FALSE); /* lookup text dimensions */ hDC = GetDC(hWnd); GetTextMetrics(hDC, &textmetric); nLineHeight = textmetric.tmExternalLeading + textmetric.tmHeight; main_rect.left = GetDeviceCaps(hDC, LOGPIXELSX) / 4; /* 1/4 inch */ main_rect.right = GetDeviceCaps(hDC, HORZRES); main_rect.top = GetDeviceCaps(hDC, LOGPIXELSY) / 4; /* 1/4 inch */ ReleaseDC(hWnd, hDC); main_rect.bottom = main_rect.top + nLineHeight; osi_InitPanic(afsd_notifier); afsi_start(); code = afsd_InitCM(&reason); if (code != 0) osi_panic(reason, __FILE__, __LINE__); code = afsd_InitDaemons(&reason); if (code != 0) osi_panic(reason, __FILE__, __LINE__); code = afsd_InitSMB(&reason, MessageBox); if (code != 0) osi_panic(reason, __FILE__, __LINE__); ShowWindow(hWnd, SW_SHOWMINNOACTIVE); UpdateWindow(hWnd); return (TRUE); }
int Wout::GetAverageTextWidth() { GetTextMetrics(hDC, &textInfo); return textInfo.tmAveCharWidth; }
void PaintClc(HWND hwnd, struct ClcData *dat, HDC hdc, RECT * rcPaint) { HDC hdcMem; RECT clRect; int y, indent, index, fontHeight; struct ClcGroup *group; HFONT hOldFont; DWORD style = GetWindowLong(hwnd, GWL_STYLE); int status = GetGeneralisedStatus(); int grey = 0, groupCountsFontTopShift; HBRUSH hBrushAlternateGrey = NULL; // yes I know about GetSysColorBrush() COLORREF tmpbkcolour = style & CLS_CONTACTLIST ? (dat->useWindowsColours ? GetSysColor(COLOR_3DFACE) : dat->bkColour) : dat->bkColour; if (dat->greyoutFlags & pcli->pfnClcStatusToPf2(status) || style & WS_DISABLED) grey = 1; else if (GetFocus() != hwnd && dat->greyoutFlags & GREYF_UNFOCUS) grey = 1; GetClientRect(hwnd, &clRect); if (rcPaint == NULL) rcPaint = &clRect; if (IsRectEmpty(rcPaint)) return; y = -dat->yScroll; hdcMem = CreateCompatibleDC(hdc); HBITMAP hBmpOsb = CreateBitmap(clRect.right, clRect.bottom, 1, GetDeviceCaps(hdc, BITSPIXEL), NULL); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBmpOsb); { TEXTMETRIC tm; hOldFont = (HFONT)SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPS].hFont); GetTextMetrics(hdcMem, &tm); groupCountsFontTopShift = tm.tmAscent; SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPCOUNTS].hFont); GetTextMetrics(hdcMem, &tm); groupCountsFontTopShift -= tm.tmAscent; } if (style & CLS_GREYALTERNATE) hBrushAlternateGrey = CreateSolidBrush(GetNearestColor(hdcMem, RGB(GetRValue(tmpbkcolour) - 10, GetGValue(tmpbkcolour) - 10, GetBValue(tmpbkcolour) - 10))); ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); SetBkMode(hdcMem, TRANSPARENT); { HBRUSH hBrush; hBrush = CreateSolidBrush(tmpbkcolour); FillRect(hdcMem, rcPaint, hBrush); DeleteObject(hBrush); if (dat->hBmpBackground) { BITMAP bmp; HDC hdcBmp; int x, y; int maxx, maxy; int destw, desth; // XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98. SetStretchBltMode(hdcMem, HALFTONE); GetObject(dat->hBmpBackground, sizeof(bmp), &bmp); hdcBmp = CreateCompatibleDC(hdcMem); SelectObject(hdcBmp, dat->hBmpBackground); y = dat->backgroundBmpUse & CLBF_SCROLL ? -dat->yScroll : 0; maxx = dat->backgroundBmpUse & CLBF_TILEH ? clRect.right : 1; maxy = dat->backgroundBmpUse & CLBF_TILEV ? maxy = rcPaint->bottom : y + 1; switch (dat->backgroundBmpUse & CLBM_TYPE) { case CLB_STRETCH: if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { if (clRect.right * bmp.bmHeight < clRect.bottom * bmp.bmWidth) { desth = clRect.bottom; destw = desth * bmp.bmWidth / bmp.bmHeight; } else { destw = clRect.right; desth = destw * bmp.bmHeight / bmp.bmWidth; } } else { destw = clRect.right; desth = clRect.bottom; } break; case CLB_STRETCHH: if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { destw = clRect.right; desth = destw * bmp.bmHeight / bmp.bmWidth; } else { destw = clRect.right; desth = bmp.bmHeight; } break; case CLB_STRETCHV: if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { desth = clRect.bottom; destw = desth * bmp.bmWidth / bmp.bmHeight; } else { destw = bmp.bmWidth; desth = clRect.bottom; } break; default: //clb_topleft destw = bmp.bmWidth; desth = bmp.bmHeight; break; } for (; y < maxy; y += desth) { if (y < rcPaint->top - desth) continue; for (x = 0; x < maxx; x += destw) StretchBlt(hdcMem, x, y, destw, desth, hdcBmp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); } DeleteDC(hdcBmp); } } group = &dat->list; group->scanIndex = 0; indent = 0; for (index = 0; y < rcPaint->bottom;) { if (group->scanIndex == group->cl.count) { group = group->parent; indent--; if (group == NULL) break; group->scanIndex++; continue; } if (y > rcPaint->top - dat->rowHeight) { int iImage = -1; int selected = index == dat->selection && (dat->showSelAlways || dat->exStyle & CLS_EX_SHOWSELALWAYS || GetFocus() == hwnd) && group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER; int hottrack = dat->exStyle & CLS_EX_TRACKSELECT && group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER && dat->iHotTrack == index; SIZE textSize, countsSize, spaceSize; int width, checkboxWidth; char *szCounts; //alternating grey if (style & CLS_GREYALTERNATE && index & 1) { RECT rc; rc.top = y; rc.bottom = rc.top + dat->rowHeight; rc.left = 0; rc.right = clRect.right; FillRect(hdcMem, &rc, hBrushAlternateGrey); } //setup if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); else if (group->cl.items[group->scanIndex]->type == CLCIT_INFO) { if (group->cl.items[group->scanIndex]->flags & CLCIIF_GROUPFONT) ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); else ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); } else if (group->cl.items[group->scanIndex]->type == CLCIT_DIVIDER) ChangeToFont(hdcMem, dat, FONTID_DIVIDERS, &fontHeight); else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) ChangeToFont(hdcMem, dat, FONTID_NOTONLIST, &fontHeight); else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && ((group->cl.items[group->scanIndex]->flags & CONTACTF_INVISTO && GetRealStatus(group->cl.items[group->scanIndex], status) != ID_STATUS_INVISIBLE) || (group->cl.items[group->scanIndex]->flags & CONTACTF_VISTO && GetRealStatus(group->cl.items[group->scanIndex], status) == ID_STATUS_INVISIBLE) ) ) { // the contact is in the always visible list and the proto is invisible // the contact is in the always invisible and the proto is in any other mode ChangeToFont(hdcMem, dat, group->cl.items[group->scanIndex]->flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS, &fontHeight); } else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && !(group->cl.items[group->scanIndex]->flags & CONTACTF_ONLINE)) ChangeToFont(hdcMem, dat, FONTID_OFFLINE, &fontHeight); else ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); GetTextExtentPoint32(hdcMem, group->cl.items[group->scanIndex]->szText, lstrlen(group->cl.items[group->scanIndex]->szText), &textSize); width = textSize.cx; if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { szCounts = pcli->pfnGetGroupCountsText(dat, group->cl.items[group->scanIndex]); if (szCounts[0]) { GetTextExtentPoint32A(hdcMem, " ", 1, &spaceSize); ChangeToFont(hdcMem, dat, FONTID_GROUPCOUNTS, &fontHeight); GetTextExtentPoint32A(hdcMem, szCounts, lstrlenA(szCounts), &countsSize); width += spaceSize.cx + countsSize.cx; } } if ((style & CLS_CHECKBOXES && group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) || (style & CLS_GROUPCHECKBOXES && group->cl.items[group->scanIndex]->type == CLCIT_GROUP) || (group->cl.items[group->scanIndex]->type == CLCIT_INFO && group->cl.items[group->scanIndex]->flags & CLCIIF_CHECKBOX)) checkboxWidth = dat->checkboxSize + 2; else checkboxWidth = 0; //background if (selected) { int x = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace - 2; ImageList_DrawEx(dat->himlHighlight, 0, hdcMem, x, y, min(width + 5, clRect.right - x), dat->rowHeight, CLR_NONE, CLR_NONE, dat->exStyle & CLS_EX_NOTRANSLUCENTSEL ? ILD_NORMAL : ILD_BLEND25); SetTextColor(hdcMem, dat->selTextColour); } else if (hottrack) SetHotTrackColour(hdcMem, dat); //checkboxes if (checkboxWidth) { RECT rc; HANDLE hTheme = OpenThemeData(hwnd, L"BUTTON"); rc.left = dat->leftMargin + indent * dat->groupIndent; rc.right = rc.left + dat->checkboxSize; rc.top = y + ((dat->rowHeight - dat->checkboxSize) >> 1); rc.bottom = rc.top + dat->checkboxSize; DrawThemeBackground(hTheme, hdcMem, BP_CHECKBOX, group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED ? (hottrack ? CBS_CHECKEDHOT : CBS_CHECKEDNORMAL) : (hottrack ? CBS_UNCHECKEDHOT : CBS_UNCHECKEDNORMAL), &rc, &rc); CloseThemeData(hTheme); } //icon if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) iImage = group->cl.items[group->scanIndex]->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT; else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) iImage = group->cl.items[group->scanIndex]->iImage; if (iImage != -1) { /*COLORREF colourFg=dat->selBkColour; int mode=ILD_NORMAL; if(selected) mode=ILD_SELECTED; else if(hottrack) {mode=ILD_FOCUS; colourFg=dat->hotTextColour;} else if(group->cl.items[group->scanIndex]->type==CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags&CONTACTF_NOTONLIST) {colourFg=dat->fontInfo[FONTID_NOTONLIST].colour; mode=ILD_BLEND50;} ImageList_DrawEx(himlCListClc,iImage,hdcMem,dat->leftMargin+indent*dat->groupIndent+checkboxWidth,y+((dat->rowHeight-16)>>1),0,0,CLR_NONE,colourFg,mode); */ // this doesnt use CLS_CONTACTLIST since the colour prolly wont match anyway COLORREF colourFg = dat->selBkColour; int mode = ILD_NORMAL; if (hottrack) { colourFg = dat->hotTextColour; } else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) { colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; mode = ILD_BLEND50; } if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && dat->showIdle && (group->cl.items[group->scanIndex]->flags & CONTACTF_IDLE) && GetRealStatus(group->cl.items[group->scanIndex], ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) mode = ILD_SELECTED; ImageList_DrawEx(himlCListClc, iImage, hdcMem, dat->leftMargin + indent * dat->groupIndent + checkboxWidth, y + ((dat->rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); } //text if (group->cl.items[group->scanIndex]->type == CLCIT_DIVIDER) { RECT rc; rc.top = y + (dat->rowHeight >> 1); rc.bottom = rc.top + 2; rc.left = dat->leftMargin + indent * dat->groupIndent; rc.right = rc.left + ((clRect.right - rc.left - textSize.cx) >> 1) - 3; DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); TextOut(hdcMem, rc.right + 3, y + ((dat->rowHeight - fontHeight) >> 1), group->cl.items[group->scanIndex]->szText, lstrlen(group->cl.items[group->scanIndex]->szText)); rc.left = rc.right + 6 + textSize.cx; rc.right = clRect.right; DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); }
int Wout::GetTextHeight() { GetTextMetrics(hDC, &textInfo); return textInfo.tmHeight; }
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { WNDCLASS wc; HWND hWnd; MSG msg; TEXTMETRIC tm; HDC hDC; LONG cxFont; LONG cyFont; if (!hPrevInstance) { wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = MusTestWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, "MusTestIcon"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = "MusTestMenu"; wc.lpszClassName = "MusTest"; if (!RegisterClass(&wc)) return FALSE; } //Create and show main window. hWnd=CreateWindow("MusTest", "MicroScrolls", WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW, 35, 35, 250, 110, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); //Get text dimensions on which to base control sizes. hDC=GetDC(hWnd); GetTextMetrics(hDC, &tm); cxFont=tm.tmAveCharWidth; cyFont=tm.tmHeight; ReleaseDC(hWnd, hDC); //Create a 'spin' button (edit control with vertical MicroScroll CreateWindow("static", "Number 1-99:", WS_VISIBLE | WS_CHILD | SS_LEFT, 2, 2+(cyFont/4), 16*cxFont, cyFont, hWnd, (HMENU)ID_NULL, hInstance, 0L); hVertEdit=CreateWindow("edit", "50", WS_VISIBLE | WS_CHILD | ES_LEFT | WS_BORDER, 2+16*cxFont, 2, 4*cxFont, (cyFont*3)/2, hWnd, (HMENU)ID_VERTEDIT, hInstance, 0L); SendMessage(hVertEdit, EM_LIMITTEXT, 2, 0L); /* * Width is forced odd with 1+(2*cxFont) so the small triangle * looks perfectly centered. Simple aesthetics. * * Parent window is default associate. */ hVertMS=CreateWindow("MicroScroll32", "1,99,50", WS_VISIBLE | WS_CHILD | MSS_SPIN, 2+20*cxFont, 2, 1+(2*cxFont), (cyFont*3)/2, hWnd, (HMENU)ID_VERTSCROLL, hInstance, 0L); //Create a horizonal edit control with a horizontal MicroScroll hHorzEdit=CreateWindow("edit", "Horizontal Edit Control", WS_VISIBLE | WS_CHILD | ES_LEFT | WS_BORDER, 2, 2*cyFont, 30*cxFont, (cyFont*3)/2, hWnd, (HMENU)ID_VERTEDIT, hInstance, 0L); //Parent window is default associate. hHorzMS=CreateWindow("MicroScroll32", "1,99,50", WS_VISIBLE | WS_CHILD | MSS_HORIZONTAL, 2+30*cxFont, 2*cyFont, 3*cxFont, (cyFont*3)/2, hWnd, (HMENU)ID_HORZSCROLL, hInstance, 0L); //Change the horizontal MicroScroll colors to a blue base. MSCrColorSet(hHorzMS, MSCOLOR_FACE, RGB(0, 0, 255)); MSCrColorSet(hHorzMS, MSCOLOR_ARROW, RGB(255, 255, 255)); MSCrColorSet(hHorzMS, MSCOLOR_SHADOW, RGB(0, 0, 128)); MSCrColorSet(hHorzMS, MSCOLOR_HIGHLIGHT, RGB(0, 255, 255)); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
Wout & Wout::operator << (const TCHAR * szText) { // Error Checking on if (window == NULL || hDC == NULL) { MessageBox(NULL, _T("hDC or m_hWnd is NULL in Wout object"), _T("Bad Error Yo!"), MB_ICONEXCLAMATION | MB_OK); return (*this); } GetTextMetrics(hDC, &textInfo); ::SetTextColor(hDC, m_TextColor); SetBkMode(hDC, TRANSPARENT); // AD_TODO: this shouldn't be a constant, change it to a variable m_CtstringToPrint = szText; m_currtstringPos = 0; RECT rect; GetClientRect(window, &rect); if ( centerText ) { SetCursorY(rect.bottom/2 - GetTextHeight()/2); SetCursorX(rect.right/2 - (GetAverageTextWidth()*tstrlen(szText))/2); centerText = false; } if (centerX) { SetCursorX(rect.right/2 - (GetAverageTextWidth()*tstrlen(szText))/2); centerX = false; } // Algorithm to put text on screen :) while (1) { if (m_currtstringPos == m_CtstringToPrint.size()) { break; } int indexFound = (int)m_CtstringToPrint.find_first_of('\\', m_currtstringPos); if (indexFound == tstring::npos) { int tstringSizeToPrint = (int)m_CtstringToPrint.size() - m_currtstringPos; // Print it ::SetTextColor(hDC, m_TextColor); TextOut(hDC, m_CursorPosX + hdcOffsetX, m_CursorPosY + hdcOffsetY, m_CtstringToPrint.substr(m_currtstringPos, tstringSizeToPrint).c_str(), tstringSizeToPrint); m_CursorPosX += tstringSizeToPrint*textInfo.tmAveCharWidth; break; } else { // so we found some delimiter x indices away from our current tstring position. // lets print the tstring up until that index(delimiter), // then we will take care of the delimiter in the InitDelimiter function // and then well go to the top of this loop, until we are done with the tstring. int tstringSizeToPrint = (indexFound) - m_currtstringPos; // Print it ::SetTextColor(hDC, m_TextColor); TextOut(hDC, m_CursorPosX + hdcOffsetX, m_CursorPosY + hdcOffsetY, m_CtstringToPrint.substr(m_currtstringPos, tstringSizeToPrint).c_str(), tstringSizeToPrint); m_CursorPosX += tstringSizeToPrint*textInfo.tmAveCharWidth; m_currtstringPos += tstringSizeToPrint; // so now we're pointing at the delimiter InitDelim(); continue; } } return (*this); }
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxChar, cxCaps, cyChar, cyClient, iVscrollPos = 0;//滑块当前位置 HDC hdc; int i, y; PAINTSTRUCT ps; TCHAR szBuffer[10]; TEXTMETRIC tm; switch (message) { case WM_CREATE: hdc = GetDC(hwnd); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2; cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hwnd, hdc); SetScrollRange(hwnd, SB_VERT, 0, NUMLINES - 1, FALSE);//范围 SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE);//初始位置 return 0; case WM_SIZE: cyClient = HIWORD(lParam); return 0; case WM_VSCROLL: switch (LOWORD(wParam)) { case SB_LINEUP://点滚动条上方的小箭头 iVscrollPos -= 1; break; case SB_LINEDOWN://点滚动条下方的小箭头 iVscrollPos += 1; break; case SB_PAGEUP://在滚动条上方点空白位置 iVscrollPos -= cyClient / cyChar; break; case SB_PAGEDOWN://在滚动条下方点空白位置 iVscrollPos += cyClient / cyChar; break; case SB_THUMBPOSITION://在滚动条上松开鼠标 iVscrollPos = HIWORD(wParam);//这里用上了wParam break; default: break; } iVscrollPos = max(0, min(iVscrollPos, NUMLINES - 1)); if (iVscrollPos != GetScrollPos(hwnd, SB_VERT))//获取当前的位置 { SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE);//更新数值 InvalidateRect(hwnd, NULL, TRUE);//刷新界面 } return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); for (i = 0; i < NUMLINES; i++) { y = cyChar * (i - iVscrollPos); TextOut(hdc, 0, y, sysmetrics[i].szLabel, lstrlen(sysmetrics[i].szLabel)); TextOut(hdc, 22 * cxCaps, y, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc)); SetTextAlign(hdc, TA_RIGHT | TA_TOP); TextOut(hdc, 22 * cxCaps + 40 * cxChar, y, szBuffer, wsprintf(szBuffer, TEXT("%5d"), GetSystemMetrics(sysmetrics[i].iIndex))); SetTextAlign(hdc, TA_LEFT | TA_TOP); } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
void FASTCALL MakeEditSelectionVisible( HWND hwndTopWnd, HWND hwndEdit ) { #ifdef USEBIGEDIT RECT rcTopWnd; RECT rcEdit; RECT rcEditNC; RECT rcOverlap; RECT rcSelOverlap; RECT rcSel; int nSelStartOffset; int nSelEndOffset; int nEditLineHeight; BEC_SELECTION bsel; HEDIT hedit; TEXTMETRIC tm; HFONT hwndEditFont; HFONT hOldFont; int nDist; HDC hdc; /* First of all, compute the overlap. If no overlap, then * we don't have to do anything further. */ GetWindowRect( hwndTopWnd, &rcTopWnd ); GetWindowRect( hwndEdit, &rcEdit ); if( IntersectRect( &rcOverlap, &rcTopWnd, &rcEdit ) == 0 ) return; /* Compute the screen coordinates of the edit selection (!) * Only bother with the top and bottom edges. */ hedit = Editmap_Open( hwndEdit ); Editmap_GetSelection( hedit, hwndEdit, &bsel ); nSelStartOffset = (int)( Editmap_LineFromChar( hedit, hwndEdit, bsel.lo ) - Editmap_GetFirstVisibleLine( hedit, hwndEdit ) ); nSelEndOffset = (int)( Editmap_LineFromChar( hedit, hwndEdit, bsel.lo ) - Editmap_GetFirstVisibleLine( hedit, hwndEdit ) ); hwndEditFont = GetWindowFont( hwndEdit ); hdc = GetDC( hwndEdit ); hOldFont = SelectFont( hdc, hwndEditFont ); GetTextMetrics( hdc, &tm ); SelectFont( hdc, hOldFont ); ReleaseDC( hwndEdit, hdc ); nEditLineHeight = tm.tmHeight; SetRect( &rcSel, 0, nSelStartOffset * nEditLineHeight, rcEdit.right - rcEdit.left, ( nSelEndOffset + 1 ) * nEditLineHeight ); Editmap_GetRect( hedit, hwndEdit, &rcEditNC ); ClientToScreen( hwndEdit, (LPPOINT)&rcSel ); ClientToScreen( hwndEdit, (LPPOINT)(&rcSel) + 1 ); rcSel.top += rcEditNC.top; rcSel.bottom += rcEditNC.top; /* Does the selection rectangle intesect the overlap? * If so, scroll the edit control down by the distance between the selection top edge * and the top window bottom edge. */ if( IntersectRect( &rcSelOverlap, &rcOverlap, &rcSel ) == 0 ) return; if( rcEdit.bottom > rcTopWnd.bottom ) nDist = -( ( ( rcTopWnd.bottom - rcSel.top ) / nEditLineHeight ) + 1 ); else nDist = ( ( rcSel.bottom - rcTopWnd.top ) / nEditLineHeight ) + 1; if( (long)Editmap_GetFirstVisibleLine( hedit, hwndEdit ) + nDist >= 0 ) { Editmap_Scroll( hedit, hwndEdit, nDist, 0 ); return; } /* Okay. We can't scroll the edit control because the top window is completely * overlapping the edit control, or the scroll would go past the first line. So * try and move the top window. */ if( rcEdit.bottom > rcTopWnd.bottom ) nDist = rcTopWnd.top - ( rcSel.bottom + ( 2 * nEditLineHeight ) ); else nDist = ( rcTopWnd.top - rcSel.bottom ) + 1; if( rcTopWnd.top - nDist < 0 ) nDist = rcTopWnd.top - rcSel.bottom; else if( rcTopWnd.bottom - nDist > GetSystemMetrics( SM_CYSCREEN ) ) nDist = rcTopWnd.bottom - rcSel.top; SetWindowPos( hwndTopWnd, NULL, rcTopWnd.left, rcTopWnd.top - nDist, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER ); #else USEBIGEDIT HEDIT hedit; BEC_SELECTION bsel; SELRANGE lLine, lCurLine; hedit = Editmap_Open( hwndEdit ); Editmap_GetSelection( hedit, hwndEdit, &bsel ); lLine = Editmap_LineFromChar( hedit, hwndEdit, bsel.hi ); lCurLine = Editmap_GetFirstVisibleLine( hedit, hwndEdit ); if( lCurLine >= lLine ) { SendMessage( hwndEdit, SCI_GOTOPOS, bsel.hi, 0); Editmap_SetSel( hedit, hwndEdit, &bsel ); // Editmap_Scroll( hedit, hwndEdit, lLine, 0 ); return; } SendMessage( hwndEdit, SCI_MOVECARETINSIDEVIEW, 0, 0); #endif USEBIGEDIT }
BOOL CTextLayout::Layout(HDC hdc, const WCHAR *psz, UINT nCnt) { Clear(); // Count Line UINT i = 0; BOOL bNewLine = TRUE; _nLineCnt = 0; for (i = 0; i < nCnt; i++) { switch (psz[i]) { case 0x0d: case 0x0a: bNewLine = TRUE; break; default: if (bNewLine) _nLineCnt++; bNewLine = FALSE; break; } } _prgLines = (LINEINFO *)LocalAlloc(LPTR, _nLineCnt * sizeof(LINEINFO)); if (!_prgLines) return FALSE; // Count character of each line. bNewLine = TRUE; int nCurrentLine = -1; for (i = 0; i < nCnt; i++) { switch (psz[i]) { case 0x0d: case 0x0a: bNewLine = TRUE; break; default: if (bNewLine) { nCurrentLine++; _prgLines[nCurrentLine].nPos = i; _prgLines[nCurrentLine].nCnt = 1; } else { _prgLines[nCurrentLine].nCnt++; } bNewLine = FALSE; break; } } TEXTMETRIC tm; GetTextMetrics(hdc, &tm); _nLineHeight = tm.tmHeight + tm.tmExternalLeading; POINT ptCurrent; ptCurrent.x = 0; ptCurrent.y = 0; // Get the rectangle of each characters. for (i = 0; i < _nLineCnt; i++) { _prgLines[i].prgCharInfo = NULL; if (_prgLines[i].nCnt) { _prgLines[i].prgCharInfo = (CHARINFO *)LocalAlloc(LPTR, _prgLines[i].nCnt * sizeof(CHARINFO)); if (!_prgLines[i].prgCharInfo) return FALSE; UINT j; POINT ptPrev = ptCurrent; for (j = 0; j < _prgLines[i].nCnt; j++) { SIZE size; GetTextExtentPoint32(hdc, psz+_prgLines[i].nPos, j + 1, &size); ptCurrent.x = size.cx; _prgLines[i].prgCharInfo[j].rc.left = ptPrev.x; _prgLines[i].prgCharInfo[j].rc.top = ptPrev.y; _prgLines[i].prgCharInfo[j].rc.right = ptCurrent.x; _prgLines[i].prgCharInfo[j].rc.bottom = ptPrev.y + _nLineHeight; ptPrev = ptCurrent; } } ptCurrent.x = 0; ptCurrent.y += _nLineHeight; } return TRUE; }
/* ** This is cribbed from FX/fxwgl.c, and seems to implement support ** for bitmap fonts where the wglUseFontBitmapsA() code implements ** support for outline fonts. In combination they hopefully give ** fairly generic support for fonts. */ static BOOL wglUseFontBitmaps_FX(HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase) { #define VERIFY(a) a TEXTMETRIC metric; BITMAPINFO *dibInfo; HDC bitDevice; COLORREF tempColor; int i; VERIFY(GetTextMetrics(fontDevice, &metric)); dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1); dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); dibInfo->bmiHeader.biPlanes = 1; dibInfo->bmiHeader.biBitCount = 1; dibInfo->bmiHeader.biCompression = BI_RGB; bitDevice = CreateCompatibleDC(fontDevice); // Swap fore and back colors so the bitmap has the right polarity tempColor = GetBkColor(bitDevice); SetBkColor(bitDevice, GetTextColor(bitDevice)); SetTextColor(bitDevice, tempColor); // Place chars based on base line VERIFY(SetTextAlign(bitDevice, TA_BASELINE) != GDI_ERROR ? 1 : 0); for(i = 0; i < (int)numChars; i++) { SIZE size; char curChar; int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res; HBITMAP bitObject; HGDIOBJ origBmap; unsigned char *bmap; curChar = (char)(i + firstChar); // Find how high/wide this character is VERIFY(GetTextExtentPoint32(bitDevice, &curChar, 1, &size)); // Create the output bitmap charWidth = size.cx; charHeight = size.cy; // Round up to the next multiple of 32 bits bmapWidth = ((charWidth + 31) / 32) * 32; bmapHeight = charHeight; bitObject = CreateCompatibleBitmap(bitDevice, bmapWidth, bmapHeight); //VERIFY(bitObject); // Assign the output bitmap to the device origBmap = SelectObject(bitDevice, bitObject); (void) VERIFY(origBmap); VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) ); // Use our source font on the device VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT))); // Draw the character VERIFY(TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1)); // Unselect our bmap object VERIFY(SelectObject(bitDevice, origBmap)); // Convert the display dependant representation to a 1 bit deep DIB numBytes = (bmapWidth * bmapHeight) / 8; bmap = malloc(numBytes); dibInfo->bmiHeader.biWidth = bmapWidth; dibInfo->bmiHeader.biHeight = bmapHeight; res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap, dibInfo, DIB_RGB_COLORS); //VERIFY(res); // Create the GL object glNewList(i + listBase, GL_COMPILE); glBitmap(bmapWidth, bmapHeight, 0.0, (GLfloat)metric.tmDescent, (GLfloat)charWidth, 0.0, bmap); glEndList(); // CheckGL(); // Destroy the bmap object DeleteObject(bitObject); // Deallocate the bitmap data free(bmap); } // Destroy the DC VERIFY(DeleteDC(bitDevice)); free(dibInfo); return TRUE; #undef VERIFY }
int WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) { WIN_DialogData *dialog; int i, x, y; UINT_PTR which; const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons; HFONT DialogFont; SIZE Size; RECT TextSize; wchar_t* wmessage; TEXTMETRIC TM; const int ButtonWidth = 88; const int ButtonHeight = 26; const int TextMargin = 16; const int ButtonMargin = 12; /* Jan 25th, 2013 - [email protected] * * * I've tried to make this more reasonable, but I've run in to a lot * of nonsense. * * The original issue is the code was written in pixels and not * dialog units (DLUs). All DialogBox functions use DLUs, which * vary based on the selected font (yay). * * According to MSDN, the most reliable way to convert is via * MapDialogUnits, which requires an HWND, which we don't have * at time of template creation. * * We do however have: * The system font (DLU width 8 for me) * The font we select for the dialog (DLU width 6 for me) * * Based on experimentation, *neither* of these return the value * actually used. Stepping in to MapDialogUnits(), the conversion * is fairly clear, and uses 7 for me. * * As a result, some of this is hacky to ensure the sizing is * somewhat correct. * * Honestly, a long term solution is to use CreateWindow, not CreateDialog. * * * In order to get text dimensions we need to have a DC with the desired font. * I'm assuming a dialog box in SDL is rare enough we can to the create. */ HDC FontDC = CreateCompatibleDC(0); { /* Create a duplicate of the font used in system message boxes. */ LOGFONT lf; NONCLIENTMETRICS NCM; NCM.cbSize = sizeof(NCM); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0); lf = NCM.lfMessageFont; DialogFont = CreateFontIndirect(&lf); } /* Select the font in to our DC */ SelectObject(FontDC, DialogFont); { /* Get the metrics to try and figure our DLU conversion. */ GetTextMetrics(FontDC, &TM); s_BaseUnitsX = TM.tmAveCharWidth + 1; s_BaseUnitsY = TM.tmHeight; } /* Measure the *pixel* size of the string. */ wmessage = WIN_UTF8ToString(messageboxdata->message); SDL_zero(TextSize); Size.cx = DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT); /* Add some padding for hangs, etc. */ TextSize.right += 2; TextSize.bottom += 2; /* Done with the DC, and the string */ DeleteDC(FontDC); SDL_free(wmessage); /* Increase the size of the dialog by some border spacing around the text. */ Size.cx = TextSize.right - TextSize.left; Size.cy = TextSize.bottom - TextSize.top; Size.cx += TextMargin * 2; Size.cy += TextMargin * 2; /* Ensure the size is wide enough for all of the buttons. */ if (Size.cx < messageboxdata->numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin) Size.cx = messageboxdata->numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin; /* Add vertical space for the buttons and border. */ Size.cy += ButtonHeight + TextMargin; dialog = CreateDialogData(Size.cx, Size.cy, messageboxdata->title); if (!dialog) { return -1; } if (!AddDialogStatic(dialog, TextMargin, TextMargin, TextSize.right - TextSize.left, TextSize.bottom - TextSize.top, messageboxdata->message)) { FreeDialogData(dialog); return -1; } /* Align the buttons to the right/bottom. */ x = Size.cx - (ButtonWidth + ButtonMargin) * messageboxdata->numbuttons; y = Size.cy - ButtonHeight - ButtonMargin; for (i = messageboxdata->numbuttons - 1; i >= 0; --i) { SDL_bool isDefault; if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) { isDefault = SDL_TRUE; } else { isDefault = SDL_FALSE; } if (!AddDialogButton(dialog, x, y, ButtonWidth, ButtonHeight, buttons[i].text, i, isDefault)) { FreeDialogData(dialog); return -1; } x += ButtonWidth + ButtonMargin; } /* FIXME: If we have a parent window, get the Instance and HWND for them */ which = DialogBoxIndirect(NULL, (DLGTEMPLATE*)dialog->lpDialog, NULL, (DLGPROC)MessageBoxDialogProc); *buttonid = buttons[which].buttonid; FreeDialogData(dialog); return 0; }
LRESULT WINAPI LVEdit_WndProc ( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam ) { LRESULT lResult = 0; BOOL bCallOrigWndProc = FALSE; static int tmHeight = 0; switch (uMessage) { case WM_ERASEBKGND: { RECT rc; HDC hdc = ( HDC )wParam; GetClientRect ( hWnd, &rc ); Rectangle ( hdc, rc.left, rc.top, rc.right, rc.bottom ); return -1; } case WM_GETDLGCODE: return ( LRESULT )DLGC_WANTARROWS | DLGC_WANTALLKEYS; case WM_SETFONT: { HDC hdc; TEXTMETRIC tm; CallWindowProc( ( FARPROC )GetClassLong ( hWnd, GCL_WNDPROC ), hWnd, uMessage, wParam, lParam ); hdc = GetDC ( hWnd ); GetTextMetrics ( hdc, &tm ); tmHeight = tm.tmHeight; ReleaseDC ( hWnd, hdc ); break; } case WM_KEYDOWN: CallWindowProc( ( FARPROC )GetClassLong ( hWnd, GCL_WNDPROC ), hWnd, uMessage, wParam, lParam ); if ( ( int )wParam == VK_ESCAPE || ( int )wParam == VK_RETURN ) SendMessage ( GetParent ( hWnd ), uMessage, wParam, lParam ); else { RECT rect; char szText[MAXSTRING]; UINT edtStyle; RECT rcText; HDC hDC = GetDC ( hWnd ); #if 0 RECT rcDad; SIZE size; HWND hwParent = GetParent ( hWnd ); GetWindowRect ( hWnd, &rect ); MapWindowPoints ( ( HWND )NULL, hwParent, ( LPPOINT )&rect.left, 2 ); GetClientRect ( hwParent, &rcDad ); GetWindowText ( hWnd, szText, MAXSTRING ); GetTextExtentPoint32 ( hDC, szText, lstrlen ( szText ), &size ); #else GetWindowText ( hWnd, szText, MAXSTRING ); GetWindowRect ( hWnd, &rect ); SetRect ( &rcText, 0, 0, rect.right - rect.left, rect.bottom - rect.top ); #endif edtStyle = GetWindowLong ( hWnd, GWL_STYLE ); if ( edtStyle & ES_MULTILINE ) { DrawText ( hDC, szText, lstrlen ( szText ),&rcText, DT_CALCRECT | DT_WORDBREAK ); #if 1 if ( rcText.bottom > rect.bottom - rect.top ) SetWindowPos ( hWnd, ( HWND )NULL, 0, 0, rect.right-rect.left, rcText.bottom, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOZORDER ); #endif } else { DrawText ( hDC, szText, lstrlen ( szText ),&rcText, DT_CALCRECT | DT_LEFT ); if ( rcText.right - rcText.left < 50 ) rcText.right = rcText.left + 50; #if 1 SetWindowPos ( hWnd, ( HWND )NULL, 0, 0, rcText.right - rcText.left + 5, rcText.bottom, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOZORDER ); #endif } ReleaseDC ( hWnd, hDC ); } break; default: return CallWindowProc( ( FARPROC )GetClassLong ( hWnd, GCL_WNDPROC ), hWnd, uMessage, wParam, lParam ); } if ( bCallOrigWndProc ) lResult = CallWindowProc( ( FARPROC )GetClassLong ( hWnd, GCL_WNDPROC ), hWnd, uMessage, wParam, lParam ); return lResult; }
void mswin_menu_window_size (HWND hWnd, LPSIZE sz) { TEXTMETRIC tm; HWND control; HGDIOBJ saveFont; HDC hdc; PNHMenuWindow data; int i; RECT rt, wrt; int extra_cx; GetClientRect(hWnd, &rt); sz->cx = rt.right - rt.left; sz->cy = rt.bottom - rt.top; GetWindowRect(hWnd, &wrt); extra_cx = (wrt.right-wrt.left) - sz->cx; data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); if(data) { control = GetMenuControl(hWnd); hdc = GetDC(control); if( data->type==MENU_TYPE_MENU ) { /* Calculate the width of the list box. */ saveFont = SelectObject(hdc, mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE)); GetTextMetrics(hdc, &tm); for(i=0; i<data->menu.size; i++ ) { LONG menuitemwidth = 0; int column; char *p, *p1; p1 = data->menu.items[i].str; p = strchr(data->menu.items[i].str, '\t'); column = 0; for (;;) { TCHAR wbuf[BUFSZ]; RECT tabRect; SetRect ( &tabRect, 0, 0, 1, 1 ); if (p != NULL) *p = '\0'; /* for time being, view tab field as zstring */ DrawText(hdc, NH_A2W(p1, wbuf, BUFSZ), /*JP strlen(p1), */ -1, &tabRect, DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_SINGLELINE ); /* it probably isn't necessary to recompute the tab width now, but do so * just in case, honoring the previously computed value */ menuitemwidth += max(data->menu.tab_stop_size[column], tabRect.right - tabRect.left); if (p != NULL) *p = '\t'; else /* last string so, */ break; /* add the separation only when not the last item */ /* in the last item, we break out of the loop, in the statement just above */ menuitemwidth += TAB_SEPARATION; ++column; p1 = p + 1; p = strchr(p1, '\t'); } sz->cx = max(sz->cx, (LONG)(2*TILE_X + menuitemwidth + tm.tmAveCharWidth*12 + tm.tmOverhang)); } SelectObject(hdc, saveFont); } else { /* do not change size for text output - the text will be formatted to fit any window */ } sz->cx += extra_cx; ReleaseDC(control, hdc); } }
void text_copy_to_clipboard(TW *tw) { int size, count; HGLOBAL hGMem; #ifdef WINDOWS_NO_UNICODE LPSTR cbuf, cp; HDC hdc; TEXTMETRIC tm; #else LPWSTR cbuf, cp; #endif UINT type; int i; size = tw->ScreenSize.y * (tw->ScreenSize.x + 2) + 1; size *= CHARSIZE; hGMem = GlobalAlloc(GHND | GMEM_SHARE, (DWORD)size); #ifdef WINDOWS_NO_UNICODE cbuf = cp = (LPSTR)GlobalLock(hGMem); #else cbuf = cp = (LPWSTR)GlobalLock(hGMem); #endif if (cp == NULL) return; for (i=0; i<tw->ScreenSize.y; i++) { count = tw->ScreenSize.x; memcpy(cp, tw->ScreenBuffer + tw->ScreenSize.x*i, count*CHARSIZE); /* remove trailing spaces */ for (count=count-1; count>=0; count--) { if (cp[count]!=' ') break; cp[count] = '\0'; } cp[++count] = '\r'; cp[++count] = '\n'; cp[++count] = '\0'; cp += count; } /* Now remove completely empty trailing lines */ while (cp >= cbuf+4) { if ((cp[-3] != '\n') || (cp[-4] != '\r')) break; cp -= 2; *cp = '\0'; } #ifdef WINDOWS_NO_UNICODE size = strlen(cbuf) + 1; #else size = CHARSIZE*(wcslen(cbuf) + 1); #endif GlobalUnlock(hGMem); hGMem = GlobalReAlloc(hGMem, (DWORD)size, GHND | GMEM_SHARE); #ifdef WINDOWS_NO_UNICODE /* find out what type to put into clipboard */ hdc = GetDC(tw->hwnd); SelectFont(hdc, tw->hfont); GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm); if (tm.tmCharSet == OEM_CHARSET) type = CF_OEMTEXT; else type = CF_TEXT; ReleaseDC(tw->hwnd, hdc); #else type = CF_UNICODETEXT; #endif /* give buffer to clipboard */ OpenClipboard(tw->hwnd); EmptyClipboard(); SetClipboardData(type, hGMem); CloseClipboard(); }
RenderQueue* BREW::CreateSpinButtonDrawable( SharedPtr<const SpinButton> spinbutton ) const { sf::Color border_color( GetProperty<sf::Color>( "BorderColor", spinbutton ) ); sf::Color background_color( GetProperty<sf::Color>( "BackgroundColor", spinbutton ) ); sf::Color text_color( GetProperty<sf::Color>( "Color", spinbutton ) ); sf::Color cursor_color( GetProperty<sf::Color>( "Color", spinbutton ) ); float text_padding( GetProperty<float>( "Padding", spinbutton ) ); float cursor_thickness( GetProperty<float>( "Thickness", spinbutton ) ); float border_width( GetProperty<float>( "BorderWidth", spinbutton ) ); int border_color_shift( GetProperty<int>( "BorderColorShift", spinbutton ) ); const sf::Font& font( *GetResourceManager().GetFont( GetProperty<std::string>( "FontName", spinbutton ) ) ); const unsigned int& font_size( GetProperty<unsigned int>( "FontSize", spinbutton ) ); float stepper_aspect_ratio( GetProperty<float>( "StepperAspectRatio", spinbutton ) ); sf::Color stepper_color( GetProperty<sf::Color>( "StepperBackgroundColor", spinbutton ) ); sf::Color stepper_border_color( GetProperty<sf::Color>( "BorderColor", spinbutton ) ); sf::Color stepper_arrow_color( GetProperty<sf::Color>( "StepperArrowColor", spinbutton ) ); RenderQueue* queue( new RenderQueue ); // Pane. queue->Add( Renderer::Get().CreatePane( sf::Vector2f( 0.f, 0.f ), sf::Vector2f( spinbutton->GetAllocation().width, spinbutton->GetAllocation().height ), border_width, background_color, border_color, -border_color_shift ) ); float button_width = ( spinbutton->GetAllocation().height / 2.f ) * stepper_aspect_ratio; // Up Stepper. queue->Add( Renderer::Get().CreatePane( sf::Vector2f( spinbutton->GetAllocation().width - button_width - border_width, border_width ), sf::Vector2f( button_width, spinbutton->GetAllocation().height / 2.f - border_width ), border_width, stepper_color, stepper_border_color, spinbutton->IsIncreaseStepperPressed() ? -border_color_shift : border_color_shift ) ); // Up Stepper Triangle. queue->Add( Renderer::Get().CreateTriangle( sf::Vector2f( spinbutton->GetAllocation().width - button_width / 2.f - border_width, ( spinbutton->IsIncreaseStepperPressed() ? 1.f : 0.f ) + border_width + spinbutton->GetAllocation().height / 6.f ), sf::Vector2f( spinbutton->GetAllocation().width - button_width / 4.f * 3.f - border_width, ( spinbutton->IsIncreaseStepperPressed() ? 1.f : 0.f ) + border_width + spinbutton->GetAllocation().height / 3.f ), sf::Vector2f( spinbutton->GetAllocation().width - button_width / 4.f - border_width, ( spinbutton->IsIncreaseStepperPressed() ? 1.f : 0.f ) + border_width + spinbutton->GetAllocation().height / 3.f ), stepper_arrow_color ) ); // Down Stepper. queue->Add( Renderer::Get().CreatePane( sf::Vector2f( spinbutton->GetAllocation().width - button_width - border_width, spinbutton->GetAllocation().height / 2.f ), sf::Vector2f( button_width, spinbutton->GetAllocation().height / 2.f - border_width ), border_width, stepper_color, stepper_border_color, spinbutton->IsDecreaseStepperPressed() ? -border_color_shift : border_color_shift ) ); // Down Stepper Triangle. queue->Add( Renderer::Get().CreateTriangle( sf::Vector2f( spinbutton->GetAllocation().width - button_width / 2.f - border_width, ( spinbutton->IsDecreaseStepperPressed() ? 1.f : 0.f ) + spinbutton->GetAllocation().height - border_width - spinbutton->GetAllocation().height / 6.f ), sf::Vector2f( spinbutton->GetAllocation().width - button_width / 4.f - border_width, ( spinbutton->IsDecreaseStepperPressed() ? 1.f : 0.f ) + spinbutton->GetAllocation().height - border_width - spinbutton->GetAllocation().height / 3.f ), sf::Vector2f( spinbutton->GetAllocation().width - button_width / 4.f * 3.f - border_width, ( spinbutton->IsDecreaseStepperPressed() ? 1.f : 0.f ) + spinbutton->GetAllocation().height - border_width - spinbutton->GetAllocation().height / 3.f ), stepper_arrow_color ) ); float line_height = GetFontLineHeight( font, font_size ); sf::Text vis_label( spinbutton->GetVisibleText(), font, font_size ); vis_label.setColor( text_color ); vis_label.setPosition( text_padding, spinbutton->GetAllocation().height / 2.f - line_height / 2.f ); queue->Add( Renderer::Get().CreateText( vis_label ) ); // Draw cursor if spinbutton is active and cursor is visible. if( spinbutton->HasFocus() && spinbutton->IsCursorVisible() ) { sf::String cursor_string( spinbutton->GetVisibleText() ); if( spinbutton->GetCursorPosition() - spinbutton->GetVisibleOffset() < cursor_string.getSize() ) { cursor_string.erase( spinbutton->GetCursorPosition() - spinbutton->GetVisibleOffset(), cursor_string.getSize() ); } // Get metrics. sf::Vector2f metrics( GetTextMetrics( cursor_string, font, font_size ) ); queue->Add( Renderer::Get().CreateRect( sf::FloatRect( metrics.x + text_padding, spinbutton->GetAllocation().height / 2.f - line_height / 2.f, cursor_thickness, line_height ), cursor_color ) ); } return queue; }
// Draw text within margins, left-justified, with word-wrap. // Draw to <hdc> context, so it supports display and bitmaps // (bitmap must already be created and selected into context). // Draw boxes for each word on EyeLink tracker display if <dotrack> set // Use font selected with get_new_font(), and draws it in <color> // RECT <margins> sets margins, and <lspace> sets pixels between lines void draw_text_box(HDC hdc, char *txt, COLORREF color, RECT margins, int lspace, int dotrack) { short x, y; // drawing position char *sword, *eword; // word start, end pointer int swx, ewx; // word start, end position char *sispace, *c; // text pointers int height; // height of characters SIZE size; TEXTMETRIC tm; if(dotrack) eyecmd_printf("clear_screen 0"); // clear eye tracker display SetBkMode(hdc, TRANSPARENT); // set text color SetTextColor(hdc, color); SelectObject(hdc, current_font); // Select cached font into context GetTextMetrics(hdc, &tm); // Get height of characters height = tm.tmHeight; SetTextJustification(hdc, 0, 0) ; // set normal text spacing SetTextAlign(hdc, TA_LEFT | TA_TOP); x = (short)margins.left; // initial drawing position y = (short)margins.top; c = txt; // initial text to scan while(*c) // loop through lines of text { nextword: // START NEW WORD: sispace = c; // scan over any leading spaces while(*c==' ') c++; if(c!=sispace) // advance over the spaces (if any) { GetTextExtentPoint32(hdc, sispace, c-sispace, &size); x += (short)size.cx; } if(*c==0) break; // handle end-of-text if(*c=='\n') // handle end-of-line before word { c++; // skip over end-of-line character nextline: // START NEW LINE: x = (short)margins.left; // return to start of line y += lspace; // top of new line if(y+height > margins.bottom) break; // stop if it would go outside margins goto nextword; // continue to print } swx = x; // continue in current line: sword = c; // record start of this word while(*c && !isspace(*c) && *c!='\n') c++; // scan till end of word if(sword==c) goto nextword; // no word: continue by skipping spaces eword = c; // record end of word GetTextExtentPoint32(hdc, sword, eword-sword, &size); // width of word ewx = size.cx + swx; // position of end of word if(ewx > margins.right) // would it extend past right margin? { c = sword; // restore text pointer goto nextline; // start a new line with current word } TextOut(hdc, x, y, sword, eword-sword); // Print the word if(dotrack) // draw box on EyeLink display eyecmd_printf("draw_box %d %d %d %d 15", swx, y, ewx, y+height); x = ewx; // update current printing location } GdiFlush(); // ADDED for Wimdows 2000/XP: Forces drawing to be immediate SelectObject(hdc, GetStockObject(SYSTEM_FONT)); // deselect the font }
LRESULT onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) { LPDRAWITEMSTRUCT lpdis; PNHMenuItem item; PNHMenuWindow data; TEXTMETRIC tm; HGDIOBJ saveFont; HDC tileDC; short ntile; int t_x, t_y; int x, y; TCHAR wbuf[BUFSZ]; RECT drawRect; COLORREF OldBg, OldFg, NewBg; char *p, *p1; int column; lpdis = (LPDRAWITEMSTRUCT) lParam; /* If there are no list box items, skip this message. */ if (lpdis->itemID == -1) return FALSE; data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); item = &data->menu.items[lpdis->itemID]; tileDC = CreateCompatibleDC(lpdis->hDC); saveFont = SelectObject(lpdis->hDC, mswin_get_font(NHW_MENU, item->attr, lpdis->hDC, FALSE)); NewBg = mswin_get_color(NHW_MENU, MSWIN_COLOR_BG); OldBg = SetBkColor(lpdis->hDC, NewBg); OldFg = SetTextColor(lpdis->hDC, mswin_get_color(NHW_MENU, MSWIN_COLOR_FG)); GetTextMetrics(lpdis->hDC, &tm); x = lpdis->rcItem.left + 1; /* print check mark if it is a "selectable" menu */ if( data->how!=PICK_NONE ) { if( NHMENU_IS_SELECTABLE(*item) ) { HGDIOBJ saveBrush; HBRUSH hbrCheckMark; char buf[2]; switch(item->count) { case -1: hbrCheckMark = CreatePatternBrush(data->bmpChecked); break; case 0: hbrCheckMark = CreatePatternBrush(data->bmpNotChecked); break; default: hbrCheckMark = CreatePatternBrush(data->bmpCheckedCount); break; } y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; SetBrushOrgEx(lpdis->hDC, x, y, NULL); saveBrush = SelectObject(lpdis->hDC, hbrCheckMark); PatBlt(lpdis->hDC, x, y, TILE_X, TILE_Y, PATCOPY); SelectObject(lpdis->hDC, saveBrush); DeleteObject(hbrCheckMark); x += TILE_X + 5; if(item->accelerator!=0) { buf[0] = item->accelerator; buf[1] = '\x0'; SetRect( &drawRect, x, lpdis->rcItem.top, lpdis->rcItem.right, lpdis->rcItem.bottom ); /*JP DrawText(lpdis->hDC, NH_A2W(buf, wbuf, 2), 1, &drawRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); */ DrawText(lpdis->hDC, NH_A2W(buf, wbuf, 2), -1, &drawRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); } x += tm.tmAveCharWidth + tm.tmOverhang + 5; } else { x += TILE_X + tm.tmAveCharWidth + tm.tmOverhang + 10; } } /* print glyph if present */ if( item->glyph != NO_GLYPH ) { HGDIOBJ saveBmp; saveBmp = SelectObject(tileDC, GetNHApp()->bmpTiles); ntile = glyph2tile[ item->glyph ]; t_x = (ntile % TILES_PER_LINE)*TILE_X; t_y = (ntile / TILES_PER_LINE)*TILE_Y; y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; nhapply_image_transparent( lpdis->hDC, x, y, TILE_X, TILE_Y, tileDC, t_x, t_y, TILE_X, TILE_Y, TILE_BK_COLOR ); SelectObject(tileDC, saveBmp); } x += TILE_X + 5; /* draw item text */ if( item->has_tab ) { p1 = item->str; p = strchr(item->str, '\t'); column = 0; SetRect( &drawRect, x, lpdis->rcItem.top, min(x + data->menu.tab_stop_size[0], lpdis->rcItem.right), lpdis->rcItem.bottom ); for (;;) { TCHAR wbuf[BUFSZ]; if (p != NULL) *p = '\0'; /* for time being, view tab field as zstring */ DrawText(lpdis->hDC, NH_A2W(p1, wbuf, BUFSZ), /*JP strlen(p1), */ -1, &drawRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE ); if (p != NULL) *p = '\t'; else /* last string so, */ break; p1 = p + 1; p = strchr(p1, '\t'); drawRect.left = drawRect.right + TAB_SEPARATION; ++column; drawRect.right = min (drawRect.left + data->menu.tab_stop_size[column], lpdis->rcItem.right); } } else { TCHAR wbuf[BUFSZ]; SetRect( &drawRect, x, lpdis->rcItem.top, lpdis->rcItem.right, lpdis->rcItem.bottom); DrawText(lpdis->hDC, NH_A2W(item->str, wbuf, BUFSZ), /*JP strlen(item->str), */ -1, &drawRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE ); } /* draw focused item */ if( item->has_focus ) { RECT client_rt; HBRUSH bkBrush; GetClientRect(lpdis->hwndItem, &client_rt); if( NHMENU_IS_SELECTABLE(*item) && data->menu.items[lpdis->itemID].count>0 && item->glyph != NO_GLYPH ) { if( data->menu.items[lpdis->itemID].count==-1 ) { _stprintf(wbuf, TEXT("Count: All") ); } else { _stprintf(wbuf, TEXT("Count: %d"), data->menu.items[lpdis->itemID].count ); } SelectObject(lpdis->hDC, mswin_get_font(NHW_MENU, ATR_BLINK, lpdis->hDC, FALSE)); /* calculate text rectangle */ SetRect( &drawRect, client_rt.left, lpdis->rcItem.top, client_rt.right, lpdis->rcItem.bottom ); /*JP DrawText(lpdis->hDC, wbuf, _tcslen(wbuf), &drawRect, */ DrawText(lpdis->hDC, wbuf, -1, &drawRect, DT_CALCRECT | DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX ); /* erase text rectangle */ drawRect.left = max(client_rt.left+1, client_rt.right - (drawRect.right - drawRect.left) - 10); drawRect.right = client_rt.right-1; drawRect.top = lpdis->rcItem.top; drawRect.bottom = lpdis->rcItem.bottom; bkBrush = CreateSolidBrush( GetBkColor(lpdis->hDC) ); FillRect(lpdis->hDC, &drawRect, bkBrush ); DeleteObject( bkBrush ); /* draw text */ /*JP DrawText(lpdis->hDC, wbuf, _tcslen(wbuf), &drawRect, */ DrawText(lpdis->hDC, wbuf, -1, &drawRect, DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX ); } /* draw focus rect */ SetRect( &drawRect, client_rt.left, lpdis->rcItem.top, client_rt.right, lpdis->rcItem.bottom ); DrawFocusRect(lpdis->hDC, &drawRect); } SetTextColor (lpdis->hDC, OldFg); SetBkColor (lpdis->hDC, OldBg); SelectObject(lpdis->hDC, saveFont); DeleteDC(tileDC); return TRUE; }