How do I create a button in c++ with my own custom image? - c++

I've been looking for a way to make a picture a button in c++ for a few hours now.. I've found stuff on using bitmaps, what what i am currently using to display the image is GDI+, because i want to use jpg/png files.
This is how i created my Image with gdiplus:
void Example_DrawImage(HDC hdc) {
Graphics graphics(hdc);
image = Image::FromFile(L"Path:/To/Image");
myBitmap = dynamic_cast<Bitmap*>(image);
Pen pen(Color(0, 0, 0, 0), 2);
graphics.DrawImage(image, 10, 10);
}
I converted that to a bitmap with:
myBitmap = dynamic_cast<Bitmap*>(image);
Then, in WM_CREATE I created a button which it's standard style is a Windows XP Button:
button = CreateWindow(TEXT("button"), TEXT("Hello"),
WS_VISIBLE | WS_CHILD | BS_BITMAP,
10, 10, /* x & y*/ 80, 25, /*width & height*/
hwnd, (HMENU) 1, hInstance, NULL
);
button is globally defined as HWND button;
All I want is to have a button that is a jpg picture. I tried doing it manually by seeing if a mouse click was inside a certain area, but I could not find a way to find the position of the Image.

Related

Disable button animation for a single application in Win32 C++

With this call
SystemParametersInfo(SPI_SETCLIENTAREAANIMATION, 0, (LPVOID)FALSE, 0);
I disable the animation of buttons in my Win32 C++ project (no MFC or anything else) that has Visual Styles Common Controls 6.0.0.0 enabled and correctly initialized by calling InitCommonControlsEx function. Is there an alternative method to do this? I am asking because I don't want to disable the animation for the whole system but ONLY for my application. The buttons I create are Custom Drawn (not Owner Drawn).
I create a button like this in the WM_CREATE message (hwndbutton is defined before as static so that I can share it between all WM messages):
hwndbutton = CreateWindowEx(0, L"BUTTON", L"example", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, x, y, width, height, hwnd, (HMENU)button_id, GetModuleHandle(NULL), NULL);
and I draw it
...
case WM_NOTIFY:
{
LPNMHDR item = (LPNMHDR)lParam;
if (item->idFrom == button_id && item->code == NM_CUSTOMDRAW)
{
LPNMCUSTOMDRAW item_draw = (LPNMCUSTOMDRAW)item;
if (item_draw->uItemState & CDIS_HOT)
{
SetDCBrushColor(item_draw->hdc, RGB(180, 180, 180));
SelectObject(item_draw->hdc, GetStockObject(DC_BRUSH));
}
else
{
SetDCBrushColor(item_draw->hdc, RGB(255, 255, 255));
SelectObject(item_draw->hdc, GetStockObject(DC_BRUSH));
}
SetDCPenColor(item_draw->hdc, RGB(0, 0, 0));
SelectObject(item_draw->hdc, GetStockObject(DC_PEN));
RoundRect(item_draw->hdc, item_draw->rc.left, item_draw->rc.top, item_draw->rc.right, item_draw->rc.bottom, 0, 0);
return CDRF_DODEFAULT; // Return would be CDRF_SKIPDEFAULT but I want to keep the text "example" drawn
}
break;
...
By "button animation", I mean for example the fading effect that takes place in the button color when you move the cursor over a button and then leave it: I would like it to be colorA when normale state or colorB when mouse is over and not colorA when normal and fade_until_you_reach_colorB when mouse is over.
Thanks
EDIT: I add two gifs
The first is what I want (and I obtain with a previous call to SystemParametersInfo) and the second is the animation I would like to avoid
What I want
What I DON'T want
Theme for individual windows and controls can be disabled as follows:
SetWindowTheme(hbutton, L" ", L" ");
Animation should already be disabled because you are using custom draw. This method will also disable mouse-hover effect.
Normally when you disable a button's theme it may look weird with old 3-D borders on newer systems. You can add BS_FLAT to button's style.

c++ win32 edit box cursor not flashing

I'm a newbie in windows programming and am continuously running into different kinds of problems, most of which I have been able to solve by myself.
My problem at hand is the caret (or cursor) shown in text areas. The thing that indicates where you are typing your text? Well it is shown, at least, but it doesn't blink like it should.
I have an EDIT box created in WM_CREATE like so:
case WM_CREATE:
{
if(!logged) {
HWND userField = CreateWindow(
"EDIT", // Predefined class; Unicode assumed
NULL, // Button text
WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT, // Styles
C_WIDTH/2 - 80, // x position
C_HEIGHT - 240, // y position
160, // Button width
25, // Button height
hwnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
// initialize NONCLIENTMETRICS structure
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(ncm);
// obtain non-client metrics
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
// create the new font
HFONT hNewFont = CreateFontIndirect(&ncm.lfMessageFont);
// set the new font
SendMessage(userField, WM_SETFONT, (WPARAM)hNewFont, 0);
}
}
break;
That is all code concerning the edit box. I'm sorry if I'm not being clear enough or my supply of code is lacking; I'm unsure of what parts of code is relevant here and what are irrelevant. I don't think I should paste my whole code here, either.
The problem, again, is that the caret in the textbox (userField) does not blink.
Please ask for more details if you need them.
Using your code, I didn't get a flashing caret. But then i added:
SetFocus( userField );
and voilĂ , a flashing caret :-)
This may not be the problem the OP was experiencing, but I was experiencing the same symptom, and I'm posting my solution here in case someone else experiences this problem...
In short, if you subclass an edit control, and handle the WM_SETFOCUS event, you need to call DefSubclassProc() or your caret won't show up. Presumably, you can call ShowCaret() yourself, but you're probably safer just calling DefSubclassProc() in case there's other processing that needs to happen.
After playing around - making my code a bit tidier and stuff - I accidentally solved this on my own
I changed
HWND userField = CreateWindow(
"EDIT", // Predefined class; Unicode assumed
NULL, // Button text
WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT, // Styles
C_WIDTH/2 - 80, // x position
C_HEIGHT - 240, // y position
160, // Button width
25, // Button height
hwnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
Into
HWND userField = CreateWindow("EDIT", NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT,
C_WIDTH/2 - 80, C_HEIGHT - 240, 160, 25, hwnd, NULL, g_hInstance, NULL);
The only difference there is the hInstance: in the first code it was apparently wrong. I changed it into my global reference of hInstance.

how to change the position of the child window inside the parent window and show the toolbar?

I have the following code which passes a window handler form OpenCV window to win32 handler, therefore I can show the grabbed images from camera to the screen and the images will show as a child window of my main API.
but the problem is that when I want to add a tooldbar to my program, the image window handler comes at the top of the toolbar. how can I sort this out?
//create a window and set the handler from openCV to win32
cv::namedWindow("test",cv::WINDOW_AUTOSIZE);
hWnd2 = (HWND) cvGetWindowHandle("test");
hParent = ::GetParent(hWnd2);
::SetParent(hWnd2, hWnd);
::ShowWindow(hParent, SW_HIDE);
_liveCapturing=true;
lastPicNr = 0;
SetWindowTextW(hStatus, L"Live Capturing ... ");
if(FullScreen()){
::ShowWindow(hWnd, SW_MAXIMIZE);
}
code for the toolbar :
HWND CreateToolbar(HWND hwnd){
HWND hTbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_TOP , 0, 0, 0, 0, hwnd, (HMENU)12, GetModuleHandle(NULL), NULL);
SendMessage(hTbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
TBBUTTON tbb[3];
TBADDBITMAP tbab;
tbab.hInst = HINST_COMMCTRL;
tbab.nID = IDB_STD_SMALL_COLOR;
SendMessage(hTbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
return hTbar;
}
Probably you have found the solution a long time ago, but i want to post my anwers in case other users need it.
You can simply add the OpenCV window with the same code you have to a child window in your window (which you set it position in advance). For example you can add it to a static text window (label) ...
If you want to move the OpenCV window, call SetWindowPos() with the desired coordinates.
SetWindowPos(hWnd2, 0, 0, 30, 0, 0, SWP_NOSIZE | SWP_NOZORDER);

How to get the background colour of CTabCtrl?

I have a CTabCtrl on my dialog, and it has several labels (CStatic) on them. The problem is, the tab control has a white background, and the labels have grey backgrounds. I know why - the parent of the labels is actually the dialog, not the tab control. However, I should be able to use CWnd::OnCtlColor to provide a custom background brush for the labels:
HBRUSH MyDialog::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor)
{
HBRUSH hBrush = __super::OnCtlColor(pDC, pWnd, nCtlColor);
const int dialogId = pWnd->GetDlgCtrlID();
if (dialogId == IDC_MY_CONTROL)
{
pDC->SetBkMode(TRANSPARENT);
hBrush = m_nullBrush;
}
return hBrush;
}
Here I use m_nullBrush to provide a brush to paint the background of the labels with, the only trouble is, I don't know how to get the tab's background colour, and instead have got it hardcoded with m_nullBrush.CreateStockObject(WHITE_BRUSH);.
Even if I re-parent the labels onto the tab control, they still end up with a grey background (even though the tab control has a white background).
How do I retrieve the background colour of a CTabCtrl?
You can put your controls in a child dialog and you must enable theme for this child dialog using EnableThemeDialogTexture.
#include "Uxtheme.h"
...
BOOL CTabDemoDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
COneDlg* OneDlg= new COneDlg;
OneDlg->Create(IDD_ONE, this);
AddPage(OneDlg, L"One");
return TRUE;
}
void CTabDemoDlg::AddPage(CDialog *Dialog, const wchar_t* Title)
{
if (IsAppThemed())
EnableThemeDialogTexture(*Dialog, ETDT_ENABLETAB);
CRect Rect;
TabCtl.GetWindowRect(Rect);
Rect.top+= 20;
Rect.InflateRect(-4, -4);
ScreenToClient(Rect);
Dialog->MoveWindow(Rect);
TabCtl.InsertItem(0, Title);
}
IDD_ONE DIALOGEX 0, 0, 224, 111
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "Check1",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,16,39,10
LTEXT "Static",IDC_STATIC,20,36,19,8
EDITTEXT IDC_EDIT1,20,48,40,14,ES_AUTOHSCROLL
PUSHBUTTON "Button1",IDC_BUTTON1,84,16,50,14
END

How to resolve aliased text in MFC controls

I'm currently in the second stage of development for a data management project I'm involved with; at the moment, we're in the stage of revamping the GUI (we're going for an office 2007-themed GUI).
At the moment I've only got experience with Dialog-based MFC projects, from which this migrates from, where we drew controls onto the dialog, then got handles to them using the GetDlgItem command, using the IDs of the controls.
Now, we're using SDI, instead of a dialog-based project, and thus, it's required to procedurally create the controls. I've had no problems creating and showing controls in the ChildView area; however, the text is very low quality and aliased. I googled the problem, but was unable to find anything particularly pertinent to the problem, indeed, the only thing which bore any real relevance was using GDI+ to draw anti-aliased text, which is fine for simple text, but I need MFC controls such as CEdit and CListBox.
Here is an image to help illustrate my problem:
I am creating both the static GDI+ text and the MFC control in the OnPaint function, as follows:
void CChildView::OnPaint()
{
CPaintDC dc(this); // device context for painting
Gdiplus::Graphics graphics(dc);
static Gdiplus::FontFamily* fontFamily = new Gdiplus::FontFamily( _T("Segoe UI") );
static Gdiplus::Font* font = new Gdiplus::Font( fontFamily, 12, Gdiplus::FontStyle::FontStyleRegular, Gdiplus::Unit::UnitPixel );
static Gdiplus::SolidBrush* solidBrush = new Gdiplus::SolidBrush( Gdiplus::Color::RoyalBlue );
Gdiplus::PointF point( 10, 10 );
graphics.SetTextRenderingHint( Gdiplus::TextRenderingHint::TextRenderingHintAntiAlias );
graphics.DrawString( _T("Hello, World!"), 13, font, point, solidBrush );
// TODO: Add your message handler code here
CEdit* pEditBox = new CEdit();
pEditBox->CreateEx( WS_EX_CLIENTEDGE, _T("EDIT"), _T("Why is this text so poor?"), WS_BORDER | WS_CHILD | WS_VISIBLE, CRect(100, 100, 300, 200), this, UINT_MAX-9 );
// Do not call CWnd::OnPaint() for painting messages
}
At the moment, I am wondering if it necessary to derive each of the controls and change their rendering methods to use GDI+ antialiased text. Hopefully their is an easier way to resolve this problem.
I will be extremely grateful for any help/advice.
Thanks in advance!
EDIT: Just for reference, I used to following to resolve my problem:
CFont* pFont = new CFont();
pFont->CreatePointFont( 120, _T("Segoe UI") );
CEdit* pEditBox = new CEdit();
pEditBox->CreateEx( WS_EX_CLIENTEDGE, _T("EDIT"), _T("Test Edit"), WS_BORDER | WS_CHILD | WS_VISIBLE, CRect(100, 100, 300, 200), this, UINT_MAX-9 );
pEditBox->SetFont( pFont );
Alternatively, the following allows for the default font for the window to be used:
CEdit* pEditBox = new CEdit();
pEditBox->CreateEx( WS_EX_CLIENTEDGE, _T("EDIT"), _T("This text is no longer poor"), WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE, CRect(100, 100, 300, 200), this, UINT_MAX-9 );
if( ::IsWindow( pEditBox->GetSafeHwnd() ) )
{
::SendMessage( pEditBox->GetSafeHwnd(), WM_SETFONT, (WPARAM)(HFONT)GetStockObject(DEFAULT_GUI_FONT), FALSE );
}
Change the font used by the edit box, it's just the default one that looks so ugly.
If you want to get the "standard" font, see e.g. SystemParametersInfo with SPI_GETNONCLIENTMETRICS argument. Of course, you can use any other font if you want to.