MFC: how to set font size? - visual-studio

I am currently using the code below to set font.
CFont my_font;
my_font.CreateFont(86, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("Arial"));
void CMyView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
...
CFont *old_font = pDC->SelectObject(&my_font);
...
}
I test using print to PDF. It works ok on my machine using Microsoft Print to PDF. But when I build and run it on another machine using a very old version of Adobe PDF, the font is too small. What is the right way to set font so that its size is consistent across different machines?

Related

MFC: Changing from CDialog to CWnd now the CStatusBar doesn't show?

To work around a problem with a CDialog being minimized when main window was minimized I decided to try using a CWnd instead. That works but now the CStatusBar doesn't show? What might I be missing or is there some requirement for it to show?
The new CWnd is created like this:
CString classname=AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, 0, 0, LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE (IDR_MAINFRAME)));
m_pDlgNowACWnd->CreateEx(0, classname, NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CRect(0, 0, 0, 0), NULL, 0)
The initialization in OnInitDialog() now being OnCreate() does the nroaml m_StatusBar.Create(this) then initializes it further with:
EnableDynamicLayout(FALSE);
// set our own height so we can scale
CStatusBarCtrl &statusctrl=m_StatusBar.GetStatusBarCtrl();
statusctrl.SetMinHeight(g_DPIHelper.Scale(20));
m_StatusBar.SetIndicators(indicators, _countof(indicators));
m_StatusBar.SetPaneInfo (0, ID_SEPARATOR, SBPS_NORMAL|SBPS_STRETCH, 0);
m_StatusBar.SetPaneInfo (sliderPane, ID_SEPARATOR, SBPS_NORMAL, g_DPIHelper.Scale(128));
m_StatusBar.SetPaneInfo (textPane, ID_SEPARATOR, SBPS_NORMAL|SBPS_POPOUT, g_DPIHelper.Scale(30));
// add this to workaround the GetSystemMatrix() issue above.
m_StatusBar.SetPaneInfo (STATUSBARspacerPane, ID_SEPARATOR, SBPS_NORMAL, 25);
// this is needed to calc location and size of bar
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, IDC_VIEW_ACHILDCWND);
EnableDynamicLayout();
auto pdlmanager=GetDynamicLayout();
if (pdlmanager) {
if (pdlmanager->Create(this)) {
pdlmanager->AddItem(m_CWndView.GetSafeHwnd(), CMFCDynamicLayout::MoveNone(), CMFCDynamicLayout::SizeHorizontalAndVertical(100, 100));
pdlmanager->AddItem(m_StatusBar.GetSafeHwnd(), CMFCDynamicLayout::MoveVertical(100), CMFCDynamicLayout::SizeHorizontal(100));
}
}
It's a status bar with a slider on it and some text.
The main CDialog now CWnd has two children a CWnd and a CStatusBar. The initial size of the dialog/window is 0, but then is resized to correct size when the dialog/window will be shown.
Any idea what I may be missing or doing wrong on converting from CDialog to a CWnd ?
Everything else works, just the CStatusBar not showing?
Thanks.
Update:
It appears to be the CStatusBar height being zero. I did a test of creating the CWnd being CRect(0, 0, 10, 50) instead of all zeros and the CStatusBar shows (although with a height of 11 which is much shorter than it should be). It seems the statusctrl.SetMinHeight(g_DPIHelper.Scale(20)) call doesn't work when using CWnd? The resizing takes place in RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, IDC_VIEW_ACHILDCWND); I set a breakpoint on CStatusBar::OnSize() and noticed when a CDialog it had the correct size but not with CWnd(had zero originally now 11 with using a height of 50 on the CWnd Create()).
Since the height of the CStatusBar won't change once created and calculated during OnCreate() the size of the created CWnd needs to be tall enough for the desired CStatusBar minimum height. So instead of this:
m_pDlgNowACWnd->CreateEx(0, classname, NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CRect(0, 0, 0, 0), NULL, 0);
Do this:
CRect rccreate(0, 0, 0, MYDLG_STATUSBAR_MINHEIGHT);
CalcWindowRect(&rccreate);
m_pDlgNowACWnd->CreateEx(0, classname, NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, rccreate, NULL, 0);

How to change text size in basic text window win32 c++

I am making a very basic tic tac toe game as my first ever attempt at anything windows. I have only a small amount of basic c++ experience as well. At the top of my program i want it to display in a large font "WELCOME TO TIC-TAC-TOE!", and then right underneath it in a much smaller font something like "DEVELOPED BY ....." or something. This is the code i wrote making the text window:
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("STATIC"),TEXT("WELCOME TO TIC-TAC-TOE!"), WS_CHILD|WS_VISIBLE|SS_CENTER, 20,20,210,20,hWnd,HMENU(NULL),GetModuleHandle(NULL),NULL);
Is there a way to make the text font for "WELCOME TO TIC-TAC-TOE!" bigger? Thanks!
The following code worked if any are interested, thanks to ScottMcP-MVP for pointing me to the right website:
hwnda = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("STATIC"),TEXT("WELCOME TO TIC-TAC-TOE!"), WS_CHILD|WS_VISIBLE|SS_CENTER, 20,20,210,20,hWnd,HMENU(NULL),GetModuleHandle(NULL),NULL);
hFont=CreateFont (20, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"Arial");
SendMessage (hwnda, WM_SETFONT, WPARAM (hFont), TRUE);
I hope you save the HWND returned by CreateWindowEx: You will need it. After you create the STATIC window send it the WM_SETFONT message, as outlined here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632642(v=vs.85).aspx
Note especially the remarks on that page about font lifetime.

Save the screenshot of an application into a bitmap

I am working on a problem, where in I am trying to save the screenshot of a window(including the title bar and borders) to a PNG file. For certain applications like Google Chrome and Visual Studio, I am not able to get the complete window's image that we get with Alt + PrintScreen.
The issues are:
For Google Chrome, I am not getting the Minimize, Maximize and Close buttons
For Visual Studio, I am getting only certain parts and missing Solution Explorer and Output windows.
I have made sure the handle I use is the root window's handle
Below is the code I use to get the BitMap:
hdc = GetDCEx(hwnd, 0, DCX_WINDOW);
hDest = CreateCompatibleDC (hdc);
GetWindowRect (hwnd, &rt);
hBitmap = CreateCompatibleBitmap (hdc, rt.right - rt.left, rt.bottom - rt.top);
SelectObject(hDest, hBitmap);
BitBlt( hDest, 0, 0, rt.right - rt.left, rt.bottom - rt.top, hdc, 0, 0, SRCCOPY);
Thanks,
Raaja

Capturing a Window that is hidden or minimized

I followed this tutorial (there's a bit more than what's listed here because in my code I get a window via mouse click) for grabbing a window as a bitmap and then rendering that bitmap in a different window.
My question:
When that window is minimized or hidden (SW_HIDE) my screen capture doesn't work, so is it possible to capture a window when it is minimized or hidden?
The PrintWindow api works well, I use it for capturing thumbnails for hidden windows. Despite the name, it is different than WM_PRINT and WM_PRINTCLIENT, it works with pretty much every window except for Direct X / WPF windows.
I added some code (C#) but after reviewing how I used the code, I realized that the window isn't actually hidden when I capture its bitmap, its just off screen so this may not work for your case. Could you show the window off screen, do a print and then hide it again?
public static Bitmap PrintWindow(IntPtr hwnd)
{
RECT rc;
WinUserApi.GetWindowRect(hwnd, out rc);
Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
bool succeeded = WinUserApi.PrintWindow(hwnd, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
if (!succeeded)
{
gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(Point.Empty, bmp.Size));
}
IntPtr hRgn = WinGdiApi.CreateRectRgn(0, 0, 0, 0);
WinUserApi.GetWindowRgn(hwnd, hRgn);
Region region = Region.FromHrgn(hRgn);
if (!region.IsEmpty(gfxBmp))
{
gfxBmp.ExcludeClip(region);
gfxBmp.Clear(Color.Transparent);
}
gfxBmp.Dispose();
return bmp;
}
There are WM_PRINT and WM_PRINTCLIENT messages you can send to the window, which cause its contents to be rendered into the HDC of your choice.
However, these aren't perfect: while the standard Win32 controls handle these correctly, any custom controls in the app might not.
I am trying to get the bitmap of partially hidden controls.
I used code before that did the drawing, but included windows overlapping it. So.. maybe you want to try this.
The WM_PRINTCLIENT should (in my understanding) redraw all inside the control, even if it is not really visible.
const int WM_PRINT = 0x317, WM_PRINTCLIENT = 0x318, PRF_CLIENT = 4,
PRF_CHILDREN = 0x10, PRF_NON_CLIENT = 2,
COMBINED_PRINTFLAGS = PRF_CLIENT | PRF_CHILDREN | PRF_NON_CLIENT;
SendMessage(handle, WM_PRINTCLIENT, (int)hdc, COMBINED_PRINTFLAGS);
//GDIStuff.BitBlt(hdc, 0, 0, width, height, hdcControl, 0, 0, (int)GDIStuff.TernaryRasterOperations.SRCCOPY);
The before code is commented out now. It is based on the code found here: Pocket PC: Draw control to bitmap (accepted answer). It is basically the same as Tim Robinson suggests in this thread.
Also, have a look here
http://www.tcx.be/blog/2004/paint-control-onto-graphics/

StretchBlt fails when printing

I have a chart (in bitmap format) that I'm trying to render to a printer using StretchBlt. When drawing to the screen, StretchBlt works fine. When drawing to a CutePDF printer, it returns 0, sets the last error to ERROR_INVALID_HANDLE, and works anyway. When drawing to a PDF995 printer or a physical HP printer, it returns 0, sets the last error to ERROR_INVALID_HANDLE, and fails to draw anything.
What would cause StretchBlt to fail for certain devices? I've verified that the source bitmap is a DIB and that the destination supports StretchBlt by calling GetDeviceCaps.
Here's my code, in case it's relevant: (It's written in C++Builder, so it uses Delphi's VCL; TCanvas wraps an HDC, and TBitmap wraps an HBITMAP. VCL provides its own StretchDraw function which does not support HALFTONE; I'm getting the same problems with it.)
void PrettyStretchDraw(TCanvas *dest, const TRect& rect, TGraphic *source)
{
if (dynamic_cast<Graphics::TBitmap*>(source) && !source->Transparent) {
POINT pt;
GetBrushOrgEx(dest->Handle, &pt);
SetStretchBltMode(dest->Handle, HALFTONE);
SetBrushOrgEx(dest->Handle, pt.x, pt.y, NULL);
StretchBlt(
dest->Handle,
rect.Left,
rect.Top,
rect.Width(),
rect.Height(),
dynamic_cast<Graphics::TBitmap*>(source)->Canvas->Handle,
0,
0,
source->Width,
source->Height,
SRCCOPY);
} else {
DrawItSomeOtherWay(dest, rect, source);
}
}
StretchBlt is broken on some printer drivers (PDF995 is notable example).
I once encontered this error happening on Windows 2003 Server only (it worked on XP).
Try to reproduce the problem on other OS, and it it does not, consider it OS specific and use StretchDIBits instead on this OS.

Resources