I read code in MFC, but was confused with the code below:
void EditView::ResetDefaultFont()
{
HFONT hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
CDC* pDC = GetDC();
CFont* pFont = pDC->SelectObject(CFont::FromHandle(hFont));
pDC->SelectObject(pFont);
::DeleteObject(hFont);
}
Why CDC Select the default font first(CFont* pFont = pDC->SelectObject(CFont::FromHandle(hFont));), but select pFont again?
The first SelectObject call changes the font selected in the device context.
The second SelectObject call resets the font to whatever it was before the first call.
While that answers the "why" for the second call, which is what you ask about, I do not have any idea what the point of doing the complete call sequence is. I find no documentation results for ResetDefaultFont, neither online in MSDN Library nor in the local Visual Studio 2012 help. Just to be thorough I created a new default MFC project in VS 2012, and used the identifier ResetDefaultFont in the constructor of a class derived from CEditView. It did not compile: no such.
So,
where did you get that ResetDefaultFont function from?
The answer is quite simple.
This code is just for getting the current font of the DC.
If they had placed the code following these statements, it would have been obvious.
Related
I'm trying to change the default OS cursor to a custom one. As of now, I'm only dealing with Windows. I got an image file with the cursor I want (.png, should I change format?).
All in all, I've been searching and trying to simply change the cursor, with no success.
Also, as of now I'm looking for the most simple solution, with as few line of codes as possible.
If relevant:
-I'm using a window created with SFML(2.1).
-The following compiles but makes no difference:
HCURSOR hCursor = LoadCursor(NULL, "path/filename.png");
SetCursor(hCursor);
So, I'm seeking the knowledge of the community, any ideas?
The following works :)
It does however immediately revert back to default windows mouse:
HCURSOR hCursor = LoadCursorFromFile("path/filename.cur");
SetCursor(hCursor);
I found this LINK, which seems to be the same problem as mine.
I am however unable to apply the answer given in the link
HWND windowHandle;
int GCL_Hcursor = -12; //GCL_HCURSOR
HCURSOR hCursor = LoadCursorFromFile("Graphics/Cursors/Pointer_small.cur");
SetCursor(hCursor);
SetClassLong(windowHandle, GCL_Hcursor, (DWORD)hCursor);
I (obviously?) get:
uninitialized local variable 'windowHandle' used
After roughly 4 hours and 30 minutes trying to get a custom mouse working with SFML on Windows, I finally managed to accomplish a task for which I had expected to use no more than 5 to 10 minutes. As such, I leave here the answer to my very own question, since the internet was unable to provide it clean and clear to a noob like me. May it be useful to whoever may need it.
#include <SFML/Graphics.hpp>
#include <windows.h>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "Simple Cursor Demonstration");
// {This is what matters}
{
sf::WindowHandle wHandle;
wHandle = window.getSystemHandle();
HCURSOR Cursor = LoadCursor(NULL, IDC_HAND); // IDC_ARROW IDC_WAIT IDC_HAND... http://msdn.microsoft.com/en-us/library/ms648391%28v=vs.85%29.aspx
//HCURSOR Cursor = LoadCursorFromFile("path/filename.cur"); //.cur or .ani
SetCursor(Cursor);
SetClassLongPtr(wHandle, GCLP_HCURSOR, reinterpret_cast<LONG_PTR>(Cursor));
}
// to prove it works, just move the mouse around
// not 100% sure the following actually proves it, but the above worked wonders on the project I wanted it for
window.clear(sf::Color(sf::Color(0, 255, 0)));
window.display();
sf::sleep(sf::milliseconds(3000));
return 0; //I've read this line or equivalent is a good idea... :)
}
Sources:
-This solution was plundered from around the internet, but mainly from Overcomplicated for a Noob ,which was also mentioned by someone who deleted their answer. While being [Overcomplicated for a Noob], it does seem to provide great information on how to properly implement custom cursors on a program, as well as how to do it on apple OS thingy instead
-This was also useful.
-colinsmith mentioned the cursor file must be .cur or .ani, .png does indeed not work
Creating a Cursor from a Bitmap is described here http://www.codeproject.com/Articles/5220/Creating-a-color-cursor-from-a-bitmap
Converting a png into a Bitmap can be done easily with CImage. Simply load the PNG and Detach the HBITMAP. But a Bitmap alone is no Cursor.
Cursors are set by the window that receive WM_SETCURSOR. So "replacing" a specific Cursor will not work. You have to intercept the WM_SETCURSOR message to change the cursor that should be returned.
Your Edit2 is wrong because you Need a valid window handle to change the cursor in the class of a window. But this will never work, ifthe window handles the Cursor by ist own (see 2)
PS: It would be better to inform yourself how Windows handles Cursors before you ask how to Change it globally...
i want to display a bitmap on my Picture control,
but actually no matter what Im trying, it doesnt work.
Right now my method looks like this:
SendDlgItemMessage(hWnd ,picture_CTRL, BM_SETIMAGE , IMAGE_BITMAP, (LPARAM) MAKEINTRESOURCE(IDB_BITMAP1));
I have also already tried to use the
STM_SETIMAGE
Message, but it wont work as well.
My Picture Control property "Type" is set to "Bitmap" and my Bitmap has an ID in resource.h
Hope you guys can help :)
First, you can't just mix and match messages in standard Windows controls. BM_SETIMAGE and STM_SETIMAGE have completely different values. If you are using a Static control, use STM_SETIMAGE. If you are using a Button control, use BM_SETIMAGE.
Second, the documentation for STM_SETIMAGE says that the LPARAM must be a handle to the image. You are passing a resource ID. You need to get the handle by calling LoadImage first. For example:
HBITMAP hBitmap = reinterpret_cast<HBITMAP>(LoadImage(
GetModuleHandle(NULL),
MAKEINTRESOURCE(IDB_BITMAP1),
IMAGE_BITMAP,
0,
0,
0));
SendDlgItemMessage(
hWnd,
picture_CTRL,
STM_SETIMAGE,
IMAGE_BITMAP,
reinterpret_cast<LPARAM>(hBitmap));
Note that according to the documentation you are responsible for deleting the bitmap when you are done with it.
EDITS: Note that I had two problems in my original version of the code, both caused by copying and pasting from the question. I failed to pass the handle as the LPARAM myself and I used BM_SETIMAGE instead of STM_SETIMAGE. I will also add a note in the answer that, as Cody Gray pointed out, the MSDN documentation for a function or message will tell you whether you can use MAKEINTRESOURCE.
I would like to render video in ActiveX control (not in pop-up DirectShow window). I have:
IID_IVMRWindowlessControl
IID_IVMRFilterConfig9
CLSID_VideoMixingRenderer9
I would like to set WindowLess mode, but I don't know how to get HWND of..., exactly, of what? IEFrame, HTML element?
hr = pWc->SetVideoClippingWindow(???);
Anyone with some hint?
Regards.
First of all, add this to the constructor of your ActiveX control:
// this seemingly innocent line is _extremely_ important.
// This causes the window for the control to be created
// otherwise, you won't get an hWnd to render to!
m_bWindowOnly = true;
Your ActiveX control will have a member variable called m_hWnd that you'll be able to use as a render target. without the m_bWindowOnly variable set true, the ActiveX control won't create its own window.
Finally, pick your renderer (VMR9 for example)
CRect rcClient;
CComPtr<IBaseFilter> spRenderer;
CComPtr<IVMRWindowlessControl9> spWindowless;
// Get the client window size
::GetClientRect(m_hWnd, rcClient);
// Get the renderer filter
spRenderer.Attach( m_pGraph->GetVideoRenderer() );
if( ! spRenderer )
return E_POINTER;
spWindowless = spRenderer;
if( spWindowless )
{
spWindowless->SetVideoClippingWindow( m_hWnd );
spWindowless->SetVideoPosition(NULL, rcClient);
spWindowless.Release();
}
spRenderer.Detach();
Please note that my graph object is a custom object and that GetVideoRenderer() is one of my own functions - it returns an IBaseFilter*.
It took me ages to find this one out. ATL is poorly documented, which is a shame, because it's an excellent technology. Anyways, hope this helps!
freefallr's info is extremely helpful, but I don't think it answers your question completely. The trick with windowless activex controls is that you don't get a window. When you draw you'll just basically get a device context and you have to respond to call from the browser and only draw when it tells you to.
The interfaces required are here: http://msdn.microsoft.com/en-us/library/ms682300%28v=VS.85%29.aspx
more info here: http://msdn.microsoft.com/en-us/library/aa751970%28VS.85%29.aspx#OC96_and_Windowless_
We've been meaning to add support for this in FireBreath (http://firebreath.org) for awhile; we have support for it in all npapi browsers, but looks like we don't (yet) support IE. If you find more details, post a summary here =]
It is necessary to switch off the "ClearType" property of the default font for all dialog controls. It is possible to do that for one control by setting
logfont.lfQuality = ANTIALIASED_QUALITY
There are a lot of suggestion how to do the same for modal dialogs (http://neelaakash.wordpress.com/2007/12/31/change-default-dialog-font-of-cdialog/ and others), but that should be done for non-modal dialogs (are instantiated with new and Create(...) methods). I've tried to do that myself:
Override 'Create' method, and modify dialog template:
BOOL CActivationChildDialogLicenseInfo::Create(UINT nIDTemplate,
CWnd* pParentWnd)
{
CDialogTemplate dlt;
int nResult;
// load dialog template
if (!dlt.Load(MAKEINTRESOURCE(nIDTemplate))) return -1;
// set your own font, for example “Arial”, 10 pts.
dlt.SetFont(L"Arial", 12);
// get pointer to the modified dialog template
LPSTR pdata = (LPSTR)GlobalLock(dlt.m_hTemplate);
// let MFC know that you are using your own template
m_lpszTemplateName = NULL;
InitModalIndirect(pdata);
// display dialog box
nResult = CActivationChildDialog::Create(nIDTemplate, pParentWnd);
// unlock memory object
GlobalUnlock(dlt.m_hTemplate);
return nResult ;
}
Seems like this method do nothing (it is called, I've checked that with putting break-point inside).
I've tried to call
nResult = CActivationChildDialog::Create(NULL, pParentWnd);
...but got a lot of ASSERTs.
I've also tried to override the 'OnSetFont' method:
void CActivationChildDialogLicenseInfo::OnSetFont(CFont *pFont)
{
CActivationChildDialog::OnSetFont(pFont);
LOGFONT logfont;
pFont->GetLogFont(&logfont);
LOGFONT logfont2=logfont;
pFont->DeleteObject();
logfont2.lfItalic = true;
logfont2.lfQuality = ANTIALIASED_QUALITY;
pFont->CreateFontIndirect(&logfont2);
}
That causes ASSERT during run-time and resulted in a VERY big font being used (lost default font settings, doesn't accept new specified settings)... I don't know why.
Please advise, how can I change a default dialog font that will be "inherited" by all dialog controls?
Thank you very much.
First off: the simple, reliable way to do this is to create the dialog and then send WM_SETFONT (or call SetFont()) to the dialog and each control in it. I'll show you how to do that below, but first, here's why the two strategies you've already tried didn't (and can't) work:
Modifying the dialog template
First off, you should be calling CDialog::CreateIndirect() if you wish to use a dialog template that you've already loaded.
But don't bother. The dialog template contains only the face name and point size - it does not allow you to specify other LOGFONT values such as lfQuality. If it did, you could simply specify that in your resource definition and avoid writing any runtime code at all!
Intercepting WM_SETFONT
In theory, you could make this work. But it's not practical. Your code has several problems: first off, you'd have to intercept this message for every child control in order for it to do anything useful: the dialog itself probably doesn't render any text. But worse, you're passing the original font to the base class (which hands it to the default window procedure, which stores it internally for later use) and then immediately destroying it - this means the dialog (and everything else using that font, including all of the child controls) will be trying to draw text using a bogus font, and reverting to the default font as a result. Finally, you're creating a new font attached to a temporary object (pFont) created and destroyed by MFC - internally, the CFont object you're working with will be detached from the font handle and destroyed, leaking a handle to a font object that nothing uses.
Leaky abstractions: a note on HFONT and CFont
HFONT is a handle type that Windows uses to represent a font object. Like most of GDI, there are specific functions for creating fonts, and the general-purpose DeleteObject() function for destroying them.
CFont is a light-weight wrapper class for HFONTs. A CFont instance can be attached and detached from an existing HFONT, or used to create a new one. If a CFont instance is still attached to a HFONT when its deconstructor executes, it will call DeleteObject() to destroy the underlying object. Internally, MFC utilizes temporary CFont instances that are attached and detached from HFONTs when calling various message handlers (such as OnSetFont). It's worth remembering that internally, Windows knows nothing about CFont, and a single HFONT may belong to 0 or more CFont instances at any given point in time.
A note on fonts and WM_SETFONT
When you create a new font - whether or not it is wrapped in a CFont object - you are the owner of that font, and it is your responsibility to destroy it once you are finished using it. Passing it to WM_SETFONT (CWnd::SetFont()) doesn't change ownership! This is actually quite useful, as it allows you to pass the same font to multiple windows without worrying about which one will destroy it - you're still the owner, and so you can (and must) destroy it yourself (once there are no windows still using it).
Finally - how to quickly create and set a font on a dialog and all its children
So you should now have enough background to understand the necessary steps:
Create the dialog
Create the desired font
Pass the font to the dialog and its children (by either sending WM_SETFONT messages, or by calling CWnd::SetFont... which itself send a WM_SETFONT message).
When the dialog is destroyed, also destroy your font.
Example
// define this as a class member - class destructor then handles step four!
CFont m_nonCleartypeFont;
BOOL CActivationChildDialogLicenseInfo::Create(UINT nIDTemplate,
CWnd* pParentWnd)
{
// step one: create dialog normally
BOOL nResult = CActivationChildDialog::Create(nIDTemplate, pParentWnd);
// step two: create custom font
// relying on destructor to destroy font once we're done with it
// so be careful to only create it once!
if ( NULL == m_nonCleartypeFont.m_hObject )
{
CFont* pOriginalFont = GetFont(); // use template font as... template!
// pull information from original font
LOGFONT logfont;
pOriginalFont->GetLogFont(&logfont);
// make font adjustments:
// specify italics
logfont.lfItalic = true;
// and non-cleartype antialiasing
logfont.lfQuality = ANTIALIASED_QUALITY;
// create our font based on adjusted information
m_nonCleartypeFont.CreateFontIndirect(&logfont);
}
// step three: set our custom font on the dialog and all children
SetFont(&m_nonCleartypeFont, FALSE);
// Send message to quickly set this font for all children.
// See documentation for SendMessageToDescendants()
// - this is actually the example given!
SendMessageToDescendants(WM_SETFONT,
(WPARAM)m_nonCleartypeFont.m_hObject,
MAKELONG(FALSE, 0),
FALSE);
return nResult;
}
Please do not mark it as a dupe of this question just yet:
Bold labels in MFC
That question does not help me; for some reason I do not see the rich edit control. Instead I believe I have to do it in code. here is a sample I found:
http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2006-10/msg00245.html
My problem is that I prefer not to re-invent the wheel and test for errors myself or through QA.
Someone must have implemented this before. Please share your code.
What I would like to do is:
Keep the same font size, family, etc. as in the already created label, but make it bold and italic as well.
Keep the memory footprint reasonably low (do not create any new unnecessary objects), but do not get the app into an inconsistent state either.
I appreciate your help.
You will want to do the following before the static text control is shown on the parent window.
Get a handle to the window: CWnd * pwnd = GetDlgItem(IDC_LABEL);
Get the current font for the static text: CFont * pfont = pwnd->GetFont();
Get the characteristics of the font: LOGFONT lf; pfont->GetLogFont(&lf);
Change the lfWeight and lfItalic fields in lf.
Put a CFont object in your parent window, so it will exist for the entire lifetime of the child window.
Initialize the CFont: m_font.CreateFontIndirect(&lf);
Set the font into the static text window: pwnd->SetFont(&m_font);