MSDN SetBitmap doesn't work, CButton shows up blank - c++

I'm trying to create a button with a bmp image taken from the resources using CButton::SetBitmap(). Using this code:
BOOL MyDialog::OnInitDialog()
{
__super::OnInitDialog();
m_myBitmap=::LoadBitmap(AfxGetResourceHandle(),MAKEINTRESOURCE(IDC_MY_BITMAP ));
m_myButton.SetBitmap( m_myBitmap );
return TRUE;
}
But the button shows up gray with no image on it. I verified if my bitmap loaded correctly with GDIPlus saving it into a jpeg and everything seems fine. Why isn't the image showing up on the button?

I found it. You need to set the BS_BITMAP flag on your CButton otherwise nothing happens. Furthermore there seems to be 2 functions that allows you to modify the button style:
CButton::ModifyStyle();
CButton::SetButtonStyle();
and for some obscure reason CButton::SetButtonStyle(); wasn't setting the flag correctly for me, hence the confusion.
With correctly loaded resources this worked:
BOOL MyDialog::OnInitDialog()
{
__super::OnInitDialog();
m_myBitmap=::LoadBitmap(AfxGetResourceHandle(),MAKEINTRESOURCE(IDC_MY_BITMAP ));
m_myButton.ModifyStyle( 0, BS_BITMAP );
m_myButton.SetBitmap( m_myBitmap );
return TRUE;
}

Related

Why is my window losing its HTMEME when I call SetWindowLongPtr(GWL_STYLE) on it?

I'm coding a custom Win32 UI control that I want to incorporate visual themes in. I load themes in its WM_NCCREATE as such:
case WM_NCCREATE:
{
HTHEME hTheme = ::OpenThemeData(hWnd, L"EDIT");
assert(hTheme);
assert(::GetWindowTheme(hWnd) != 0);
}
return 1;
and then release them when control is destroyed:
case WM_DESTROY:
{
HTHEME hTheme = ::GetWindowTheme(hWnd);
assert(hTheme);
if(::CloseThemeData(hTheme) != S_OK)
{
assert(NULL);
}
}
break;
This works well, until someone tries to change that control's styles. The following call (just by itself without even changing any styles):
::SetWindowLongPtr(hChildWnd, GWL_STYLE, dwStyle);
will make GetWindowTheme on hChildWnd return NULL.
So, is it a bug or a feature?
PS. To make a reproducible Win32 example I had to adjust the stock Win32 solution from the VS 2017. (Here is its full source code.) The way it works is this: in it I create a small child control (shown in gray below) that has theme in question:
Then when you click on the white area of the main window, I try to change its styles and its theme disappears:
To see the full Win32 code for that project, I also posted it on PasteBin.
According to Window Styles document:
"After the window has been created, these styles cannot be modified,
except as noted."
Because this is not permitted, the theme engine does not always check for changed styles and in some circumstances will draw the caption based on old data. And the only guaranteed and supportable solution is for the application to destroy the window and recreate it with the new styles rather than trying to change them on the fly.
A similar discussion can be found:
http://social.msdn.microsoft.com/Forums/en/windowscompatibility/thread/7b5ef777-ff0d-4f15-afed-5588f93f0e23

QIcon not being displayed on QPushButton

I'm learning how to use Qt for C++ programming. I have this image I want to display after when I click at a button and the position on a matrix related to that button is equal to -1, I also want to clear the text on that same button, my code up to now for that part is:
if(Tabuleiro[x][y] == -1){
this->Botoes[x][y]->setText("");
this->Botoes[x][y]->setIcon(QIcon("bomba.png"));
}
Being that Tabuleiro is a matrix of int, Botoes is a matrix of pointers to QPushButtons and "bomba.png" is the image I want to display. The image is in the same folder as the project, but once I run it is not displayed. I also tryed using Qt Resource system, I created a new resource called imagens.qrc on it I created a prefix /Imagem and placed my image there, this is what the code looked like after this:
if(Tabuleiro[x][y] == -1){
this->Botoes[x][y]->setText("");
this->Botoes[x][y]->setIcon(QIcon(":/Imagem/bomba.png"));
}
But it still won't work. What am I doing wrong? Also, I tryed using
this->Botoes[x][y]->text().clear();
instead of
this->Botoes[x][y]->setText("");
But it didn't work, do you know why?
Please include <QApplication> and <QStyle> and try:
this->Botoes[x][y]->setIcon( qApp->style()->standardIcon( QStyle::SP_MessageBoxWarning ) );
If it works (warning icon being displayed): then, it means you're not loading your resources correctly.
You can also check this:
QPixmap foo( ":/Imagem/bomba.png" );
bool found = !foo.isNull(); // true if png file was found, false if it was not
If false, again, it means you're not loading your resources correctly, if true, icon should be displayed in the button.
Morevover, you can also try this->Botoes[x][y]->setIconSize( QSize(16,16) ) because if someone earlier did this->Botoes[x][y]->setIconSize( QSize(0,0) ); your button icon will not be displayed!

Invalidate() function not working

I have a function that checks whenever a button check box i clicked
void CRisanjeDlg::OnBnClickedCheck1()
{
Invalidate(1);
}
And in the OnPaint method i have this code:
if(m_CheckBox1.GetState() ==1 )
{
CBrush brush;
CRect rect;
GetClientRect(rect);
brush.CreateSolidBrush(RGB(255,200,255));
rect.DeflateRect(0,0,500,0);
dc.Rectangle(rect);
dc.FillRect(rect, &brush);
}
I have a couple of other events, which trigger the OnPaint method, and if the box is checked, it draws what it has to draw.
It just doesn't work when i click the check box. The event is recognized, it's just that the Invalidate(1) does not work...
Any suggestions?
EDIT: When I uncheck the box, the function works fine. It seems the problem should be in the
if(m_CheckBox1.GetState() ==1 )
part.
EDIT2: True, the problem was in the mentioned if statement. This fixed it, don't know why. Would appreciate a further explanation.
m_CheckBox1.GetCheck() ==1
Try to use the debugger and see if you are coming inside your OnBnClickedCheck1 function
GetState returns a combination of states. Since the user is pressing on the button, you'll have BST_PUSHED and BST_FOCUS in addition to BST_CHECKED. It would have worked if you just tested for the single bit:
if ((m_CheckBox1.GetState() & BST_CHECKED) == BST_CHECKED)
Which can be simplified, since any non-zero value is true:
if (m_CheckBox1.GetState() & BST_CHECKED)

MFC: CToolTipCtrl::SetTipBkColor not working

I am trying to customize my tooltips with dark background so that they are clearly visbile. I have tried using the CToolTipCtrl::SetTipBkColor for that purpose. But I am still seeing the default style tooltip with silver gradient background with dropshadow.
Please find the sample code I have used for this purpose.
BOOL CAboutDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
m_ToolTipCtrl.Create(this, TTS_ALWAYSTIP | TTS_NOPREFIX );
m_ToolTipCtrl.Activate(TRUE);
m_ToolTipCtrl.SetDelayTime(TTDT_INITIAL, 0);
m_ToolTipCtrl.SetTipBkColor(RGB(255,0,0));
CWnd* pWnd = GetDlgItem(IDC_BUTTON1);
m_ToolTipCtrl.AddTool(pWnd,_T("TOOLTIP Displayed"));
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
Upon searching I have found that I need to disable visual styles. I don't know what it really means. I am thinking it has something to do with CToolTipCtrl:::SetWindowTheme but have no clue of what value needs to be passed.
Simply pass a blank string for the theme:
m_ToolTipCtrl.SetWindowTheme("");

Maximized Window Restores to Full Screen

Using CWnd::ShowWindow(SW_SHOWMAXIMIZED) maximizes my app window as expected.
However, when clicking the restore button on the app (or double clicking the title-bar), the restored size is the same size as the maximized window, which is confusing for the user.
Using this alternative code has the same problem:
WINDOWPLACEMENT wndpl;
GetWindowPlacement(&wndpl);
wndpl.showCmd = SW_SHOWMAXIMIZED;
SetWindowPlacement(&wndpl);
How can I keep the default un-maximized size when restoring.
I've solved my problem, and the solution might solve yours too. My problem was that even though I called SetWindowPlacement(&wndpl) within CMainFrame::OnCreate the window was not properly restored if it was maximized. I added two lines of code before SetWindowPlacement, and now it works as expected.
CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
// Obtain wndpl, maybe from registry
AfxGetApp()->m_nCmdShow = wndpl.showCmd;
wndpl.showCmd = SW_SHOW;
SetWindowPlacement(&wndpl);
}
These two lines helps underlying code not to mess things up when calling ActivateFrame, which calls ShowWindow with parameter obtained from CWinApp::m_nCmdShow.
All information are in the file with extension .RC. I never used a Maximize/Restore procedures though you should look for a 'DIALOGEX' for the same window. You can change it using any editor (notepad, ultraedit etc.)