thank you for you time in advance.
Very new to MFC and attempting to finish a cs project before Sunday. We are to create a simple program that displays polygons in a grid. Rectangles are working great, but as I begin to add triangles, I cannot for the of me figure out why the triangle dialog box refuses to display. Here is some code:
CEquilDialog.h:
#include <afxwin.h>
class CEquilDialog : public CDialog {
public:
CEquilDialog();
afx_msg void OnOK();
afx_msg void OnCancel();
int m_nSideLength;
COLORREF m_Color;
private:
DECLARE_MESSAGE_MAP()
};
CEquilDialog.cpp:
#include "CEquilDialog.h"
#include "CEquilateralIds.h"
const int TEXT_MAX = 20;
CEquilDialog::CEquilDialog() : CDialog("Equilateral Traingle") {
m_nSideLength = 0;
}
afx_msg void CEquilDialog::OnOK() {
char editText[TEXT_MAX + 1];
CEdit* SideLengthEdit = (CEdit* )(GetDlgItem(IDC_SideLength));
SideLengthEdit->GetWindowText(editText,TEXT_MAX);
m_nSideLength = atoi(editText);
if (m_nSideLength <= 0) {
EndDialog(!IDOK);
return;
}
int color = GetCheckedRadioButton(IDC_Red, IDC_Blue);
switch(color) {
case IDC_Red:
m_Color = RGB(255,0,0);
break;
case IDC_Yellow:
m_Color = RGB(255,255,0);
break;
case IDC_Blue:
m_Color = RGB(0,0,255);
break;
default:
m_Color = RGB(255,255,255);
}
EndDialog(IDOK);
}
afx_msg void CEquilDialog::OnCancel() {
m_nSideLength = 0;
EndDialog(!IDOK);
}
BEGIN_MESSAGE_MAP(CEquilDialog, CDialog)
ON_COMMAND(IDC_OK, OnOK)
ON_COMMAND(IDC_Cancel, OnCancel)
END_MESSAGE_MAP()
CEquilateralIds.h
#define IDC_OK 2000
#define IDC_Cancel 2011
#define IDC_SideLength 2012
#define IDC_Red 2013
#define IDC_Yellow 2014
#define IDC_Blue 2015
Equilateral.rc (resource file)
#include <afxres.h>
#include "CEquilateralIds.h"
Equilateral DIALOG 50,50,150,150
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Create Triangle"
{
LTEXT "Enter Side Length", IDC_STATIC, 10, 5, 50, 8
EDITTEXT IDC_SideLength, 25, 15, 60, 16
GROUPBOX "Select color", IDC_STATIC, 10, 70, 60+15, 50
AUTORADIOBUTTON "Red", IDC_Red, 25, 80, 50, 16, WS_GROUP
AUTORADIOBUTTON "Yellow", IDC_Yellow, 25, 91, 50, 16
AUTORADIOBUTTON "Blue", IDC_Blue, 25, 102, 50, 16
PUSHBUTTON "OK", IDC_OK, 10, 125, 30, 15, NOT WS_TABSTOP
PUSHBUTTON "Cancel", IDC_Cancel, 10+60+15, 125, 30, 15, NOT WS_TABSTOP
}
All of this code is identical to my rectangle files (same files just with rectangle instead of equil, also with height and width instead of just SideLength) -- and here is the CShapesWin.cpp (where the dialog box gets called):
#include <afxwin.h>
#include "CShapesWin.h"
#include "CRectDialog.h"
#include "CEquilDialog.h"
#include "CRectangleIds.h"
#include "CEquilateralIds.h"
CShapesWin::CShapesWin() {
Create(NULL, "DrawShapes");
}
afx_msg void CShapesWin::OnPaint() {
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
m_doc.Paint(dc, rect);
}
afx_msg void CShapesWin::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
CRectDialog rectDialog;
CEquilDialog equilDialog;
switch(nChar) {
case 38: // Up arrow
case 40: // Down arrow
// Pop up a dialog box and get the response
if (rectDialog.DoModal() == IDOK) {
if (m_doc.Add(new CRectangle(rectDialog.m_nHeight,
rectDialog.m_nWidth, rectDialog.m_Color)) == TRUE) {
Invalidate(TRUE);
}
}
break;
case 39: // Right arrow
case 37: // Left arrow
if (equilDialog.DoModal() == IDOK) {
if (m_doc.Add(new CEquilateral(equilDialog.m_nSideLength,
equilDialog.m_Color)) == TRUE) {
Invalidate(TRUE);
}
}
else {
MessageBox("Whoops, no dialoge box... :(");
}
break;
default:
MessageBox("Key not recognized");
}
}
BEGIN_MESSAGE_MAP(CShapesWin, CFrameWnd)
ON_WM_PAINT()
ON_WM_KEYDOWN()
END_MESSAGE_MAP()
With debugging, I have seen the call to equilDialog.DoModel() attempt to be called, but it fails everytime, whereas my rect.Dialog.DoModel() never fails.... I am at a complete lost, if anyone could help I would be so grateful!
EDIT: Thank you Brian, It seems I forgot how to use a computer! Here is a public link with the zip file: http://dl.dropbox.com/u/1734050/SO%20Polygon%20Project.zip
EDIT 2: Martin, Thank you so much, The only thing I had to do was make sure that the string in the CEquilDialog.cpp file matched in the resource file. Once I did that, the dialog box worked like a charm.
FOR ANYONE new to MFC and having Dialog box issues, please remeber the following:
In any of your dialog.cpp files when you declare the constructor:
CYourDialog::CYourDialog() : CDialog("StringToMatchInResourceFile") {
m_nSomeVariable = 0;
}
the "StringToMatchInResourceFile" must also be in the .rc file:
#include <afxres.h>
#include "CEquilateralIds.h"
StringToMatchInResourceFile DIALOG 50,50,150,150
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
...
What I did was have "Equilateral Triangle" in the dialog.cpp and then "Equilateral" in the .rc file. MFC Newbies, *take note!*a
Your dialog resource can't be found. When you call the base class constructor :CDialog("Equilateral Triangles"), you're telling MFC and the dialog manager that you have a dialog template resource with the string id "Equilateral Triangles". But your rc file doesn't have that. It has a dialog resource with the id Equilateral (which I don't see you define anywhere). Instead add IDD_EQUILATERAL as 101 to equilateralids.h and refer to it in the CDialog constructor.
It probably works right for the other case because your ID and its string match.
As an added point, without special mechanics you only get one .rc file per project. So if by chance you have two rc files, merge them into one file. This may also be going wrong because the second RC file isn't going anywhere at all.
Martyn
Related
I am attempting to create a "dark mode" for my Windows C++ app partially for fun, partially to try and fully comprehend the message passing in MFC, but I'm running into some really odd issues that I can't find explained anywhere.
I've spent the better part of today attempting to figure this out and will try my best to cite the many sources I've looked at and attempted to implement.
I believe I've successfully written message handlers for both WM_CTLCOLOR and WM_ERASEBKGND based on example code from this answer, but they don't seem to have any effect on my dialogs. I've cut the code down here, but am hoping that I've provided enough to expose my issue. If that still isn't enough, I can (reluctantly) share the entire repo.
SoftwareDlg.h
#ifndef _SOFTWAREDLG_H_INCLUDED_
#define _SOFTWAREDLG_H_INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class SoftwareDlg : public CDialog
{
// Construction
public:
SoftwareDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(SoftwareDlg)
enum { IDD = IDD_SOFTWARE_DIALOG };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(SoftwareDlg)
public:
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
BOOL PreTranslateMessage(MSG* pMsg);
CFont m_font;
CRichEditCtrl m_richEditCtrl;
// Generated message map functions
//{{AFX_MSG(SoftwareDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
/////////////////////////////////////////////////////////////////////////////
#endif
/////////////////////////////////////////////////////////////////////////////
SoftwareDlg.cpp
#include "stdafx.h"
#include <Windows.h>
#include "AboutDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//Windows Dialog inherited function overrides
/////////////////////////////////////////////////////////////////////////////
// SoftwareDlg dialog
/////////////////////////////////////////////////////////////////////////////
SoftwareDlg::SoftwareDlg(CWnd* pParent /*=NULL*/)
: CDialog(SoftwareDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(SoftwareDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void SoftwareDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(SoftwareDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(SoftwareDlg, CDialog)
//{{AFX_MSG_MAP(SoftwareDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_WM_ERASEBKGND()
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// SoftwareDlg message handlers
/////////////////////////////////////////////////////////////////////////////
BOOL SoftwareDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
CWnd* pPlaceholder = GetDlgItem(IDC_PLACEHOLDER);
if (pPlaceholder)
{
CRect rect;
pPlaceholder->GetClientRect(&rect);
if (!m_richEditCtrl.Create(WS_VISIBLE | ES_READONLY | ES_MULTILINE | ES_AUTOHSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | WS_VSCROLL, rect, this, 0))
return FALSE;
m_font.CreateFont(-11, 0, 0, 0, FW_REGULAR, 0, 0, 0, BALTIC_CHARSET, 0, 0, 0, 0, "Courier New");
m_richEditCtrl.SetFont(&m_font);
}
m_nTimerID = SetTimer(0x1234, 1000, NULL); //Used by OnTimer function to refresh dialog box & OSD
return TRUE; // return TRUE unless you set the focus to a control
}
void SoftwareDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
/////////////////////////////////////////////////////////////////////////////
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
/////////////////////////////////////////////////////////////////////////////
void SoftwareDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM)dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR SoftwareDlg::OnQueryDragIcon()
{
return (HCURSOR)m_hIcon;
}
void SoftwareDlg::OnTimer(UINT nIDEvent)
{
CDialog::OnTimer(nIDEvent);
}
void SoftwareDlg::OnDestroy()
{
if (m_nTimerID)
KillTimer(m_nTimerID);
m_nTimerID = NULL;
MSG msg;
while (PeekMessage(&msg, m_hWnd, WM_TIMER, WM_TIMER, PM_REMOVE));
CDialog::OnDestroy();
}
BOOL SoftwareDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case ' ':
Sleep(1000);
}
}
return CDialog::PreTranslateMessage(pMsg);
}
BOOL SoftwareDlg::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
CBrush myBrush(RGB(255, 0, 0)); // dialog background color
CBrush* pOld = pDC->SelectObject(&myBrush);
BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOld); // restore old brush
return bRes; // CDialog::OnEraseBkgnd(pDC);
}
HBRUSH SoftwareDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// Are we painting the IDC_MYSTATIC control? We can use
m_brush.CreateSolidBrush(RGB(136, 217, 242));
//if (pWnd->GetDlgCtrlID() == IDD_SOFTWARE_DIALOG)
// Set the text color to red
pDC->SetTextColor(RGB(255, 0, 0));
// Set the background mode for text to transparent so background will show thru.
pDC->SetBkMode(TRANSPARENT);
// Return handle to our CBrush object
hbr = m_brush;
return hbr;
}
HBRUSH SoftwareDlg::CtlColor(CDC* pDC, UINT nCtlColor)
{
HBRUSH myBrush = CreateSolidBrush(RGB(136, 217, 242));
return myBrush;
}
Resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Software.rc
//
#define IDM_ABOUTBOX 0x0010
#define IDD_ABOUTBOX 100
#define IDS_ABOUTBOX 101
#define IDD_SOFTWARE_DIALOG 102
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 141
#define _APS_NEXT_COMMAND_VALUE 32792
#define _APS_NEXT_CONTROL_VALUE 1026
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Another question, posted by the same user ~6 months earlier, was answered with somewhat similar code, but using the type of framework that contains a "WinMain" function(sorry, I can't differentiate the 2+ types yet). My program does not contain a WinMain function so I wasn't able to use the sample code directly... but another difference in this answer was that David was told to catch a WM_CTLCOLORDLG message type instead the WM_CTLCOLOR message type. I tried to catch this new message type, but IntelliSense told me it was undefined and that particular message property was completely absent from the resource view of the dialog box:
I've also attempted defining "WM_CTLCOLORDLG" myself as described on the Microsoft Docs page, but continued to get error messages when I tried handling it through "ON_MESSAGE".
My code was not an original project, but was taken from an open source sample provided with RTSS. As such, it doesn't use the standard(?) "pch.h", but "stdafx.h"(which is older I guess?). I'm not certain if that's relevant, but I feel like it may be.
I think this issue may also be causing me a lot of other growing pains as well, so any help is GREATLY appreciated.
Main problem with OP's code is that the brush is re-created every time in OnCtlColor and will keep leaking GDI handles (the debug build of MFC raises an ASSERT about this). Complete step-by-step fix below.
Declare the color and brush as members of the dialog.
class SoftwareDlg : public CDialog
{
//...
protected:
COLORREF m_color;
CBrush m_brush;
//...
Initialize the color and brush in OnInitDialog.
BOOL SoftwareDlg::OnInitDialog()
{
m_color = RGB(136, 217, 242);
m_brush.CreateSolidBrush(m_color);
CDialog::OnInitDialog();
//...
Return the brush from OnCtlColor.
HBRUSH SoftwareDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
//...
return m_brush;
}
Use the color in OnEraseBkgnd to repaint any visible area.
afx_msg BOOL SoftwareDlg::OnEraseBkgnd(CDC* pDC)
{
CRect rc;
pDC->GetClipBox(&rc);
pDC->FillSolidRect(rc, m_color);
return TRUE;
}
Set the background color to the rich edit control in OnInitDialog explicitly, since rich edit controls do not use the WM_CTLCOLOR*** messages.
BOOL SoftwareDlg::OnInitDialog()
{
//...
if (pPlaceholder)
{
//...
if (!m_richEditCtrl.Create(WS_VISIBLE | ES_READONLY | ES_MULTILINE | ES_AUTOHSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | WS_VSCROLL, rect, this, 0))
return FALSE;
m_richEditCtrl.SetBackgroundColor(FALSE, m_color);
//...
Note: if using the CDialogEx::SetBackgroundColor approach proposed in the other answer, the OnCtlColor and OnEraseBkgnd parts are covered by the CDialogEx implementation. The last step is still necessary because the WM_CTLCOLOR mechanism only covers the basic controls (static, edit, button etc) and the dialog itself. Controls other than those (rich edit control, list-view control etc) need to be handled each separately.
Simply use the CDialogEx class it supports CDialogEx::SetBackgroundColor and it does all the stuff for static and button controls.
CURRENT UI
NEW UI
I want to change the background color of a button in MFC application. I have created my user interface(UI) in MFC .I have added every controls from the toolbox.But the problem is that i want to change the background and foreground properties of a button and window.How it is possible?
please help me to change the properties of controls in MFC.In windows application we can directly change the properties in the property window.
But in the case of MFC application that is not possible.
please help me..i have not enough experience in MFC application development.....
Thanks in advance......................
code from dialer.h
class CButtonDialer : public CButton
{
// Construction
public:
CButtonDialer();
// Attributes
public:
CButton m_button;
// CButton IDC_KEY_1;
CBrush m_brush;
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CButtonDialer)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
// Implementation
public:
virtual ~CButtonDialer();
// Generated message map functions
protected:
//{{AFX_MSG(CButtonDialer)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
CFont m_FontLetters;
CMapStringToString m_map;
HTHEME m_hTheme;
void OpenTheme() { m_hTheme = OpenThemeData(m_hWnd, L"Button"); }
void CloseTheme() {
if (m_hTheme) { CloseThemeData(m_hTheme); m_hTheme = NULL; }
}
DECLARE_MESSAGE_MAP()
virtual void PreSubclassWindow();
afx_msg LRESULT OnThemeChanged();
afx_msg void OnMouseMove(UINT,CPoint);
afx_msg void OnSize(UINT type, int w, int h);
};
code from dialer.cpp file
#include "stdafx.h"
#include "ButtonDialer.h"
#include "Strsafe.h"
#include "const.h"
/////////////////////////////////////////////////////////////////////////////
// CButtonDialer
CButtonDialer::CButtonDialer()
{
//255,255,255
m_brush.CreateSolidBrush(
(173, 41, 41));
m_map.SetAt(_T("1"),_T(""));
m_map.SetAt(_T("2"),_T("ABC"));
m_map.SetAt(_T("3"),_T("DEF"));
m_map.SetAt(_T("4"),_T("GHI"));
m_map.SetAt(_T("5"),_T("JKL"));
m_map.SetAt(_T("6"),_T("MNO"));
m_map.SetAt(_T("7"),_T("PQRS"));
m_map.SetAt(_T("8"),_T("TUV"));
m_map.SetAt(_T("9"),_T("WXYZ"));
m_map.SetAt(_T("0"),_T(""));
m_map.SetAt(_T("*"),_T(""));
m_map.SetAt(_T("#"),_T(""));
}
CButtonDialer::~CButtonDialer()
{
CloseTheme();
}
BEGIN_MESSAGE_MAP(CButtonDialer, CButton)
ON_WM_THEMECHANGED()
ON_WM_MOUSEMOVE()
ON_WM_SIZE()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CButtonDialer message handlers
void CButtonDialer::PreSubclassWindow()
{
OpenTheme();
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
LOGFONT lf;
GetObject(hFont, sizeof(LOGFONT), &lf);
lf.lfHeight = 14;
StringCchCopy(lf.lfFaceName,LF_FACESIZE,_T("Microsoft Sans Serif"));
m_FontLetters.CreateFontIndirect(&lf);
DWORD dwStyle = ::GetClassLong(m_hWnd, GCL_STYLE);
dwStyle &= ~CS_DBLCLKS;
::SetClassLong(m_hWnd, GCL_STYLE, dwStyle);
}
LRESULT CButtonDialer::OnThemeChanged()
{
CloseTheme();
OpenTheme();
return 0L;
}
void CButtonDialer::OnSize(UINT type, int w, int h)
{
CButton::OnSize(type, w, h);
}
void CButtonDialer::OnMouseMove(UINT nFlags,CPoint point)
{
CRect rect;
GetClientRect(&rect);
if (rect.PtInRect(point)) {
if (GetCapture() != this) {
SetCapture();
Invalidate();
}
}
else {
ReleaseCapture();
Invalidate();
}
CButton::OnMouseMove(nFlags, point);
}
void CButtonDialer::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC dc;
dc.Attach(lpDrawItemStruct->hDC); //Get device context object
CRect rt;
rt = lpDrawItemStruct->rcItem; //Get button rect
dc.FillSolidRect(rt,dc.GetBkColor());
dc.SetBkMode(TRANSPARENT);
CRect rtl = rt;
UINT state = lpDrawItemStruct->itemState; //Get state of the button
if (!m_hTheme) {
UINT uStyle = DFCS_BUTTONPUSH;
if ( (state & ODS_SELECTED) ) {
uStyle |= DFCS_PUSHED;
rtl.left+=1;
rtl.top+=1;
}
dc.DrawFrameControl(rt, DFC_BUTTON, uStyle);
} else {
UINT uStyleTheme = RBS_NORMAL;
if ( (state & ODS_SELECTED) ) {
uStyleTheme = PBS_PRESSED;
} else if (GetCapture()==this) {
uStyleTheme = PBS_HOT;
}
DrawThemeBackground(m_hTheme, dc.m_hDC,
BP_PUSHBUTTON, uStyleTheme,
rt, NULL);
}
CString strTemp;
GetWindowText(strTemp); // Get the caption which have been set
rtl.top += 4;
CString letters;
COLORREF crOldColor;
if (m_map.Lookup(strTemp,letters)) {
rtl.left+=15;
dc.DrawText(strTemp,rtl,DT_LEFT|DT_TOP|DT_SINGLELINE); // Draw out the caption
HFONT hOldFont = (HFONT)SelectObject(dc.m_hDC, m_FontLetters);
// Do your text drawing
rtl.left += 13;
rtl.top += 4;
rtl.right -=4;
crOldColor = dc.SetTextColor(RGB(148, 167, 70));
dc.DrawText(letters,rtl,DT_LEFT | DT_TOP | DT_SINGLELINE);
dc.SetTextColor(crOldColor);
// Always select the old font back into the DC
SelectObject(dc.m_hDC, hOldFont);
} else {
//127,127,127
crOldColor = dc.SetTextColor(RGB(148, 167, 70));
dc.DrawText(strTemp,rtl,DT_CENTER|DT_TOP|DT_SINGLELINE); // Draw out the caption
dc.SetTextColor(crOldColor);
}
if ( (state & ODS_FOCUS ) ) // If the button is focused
{
int iChange = 3;
rt.top += iChange;
rt.left += iChange;
rt.right -= iChange;
rt.bottom -= iChange;
dc.DrawFocusRect(rt);
}
dc.Detach();
}
BOOL CButtonDialer::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
//255,255,255
CBrush myBrush(RGB(173, 41, 41)); // dialog background color
CBrush *pOld = pDC->SelectObject(&myBrush);
BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOld); // restore old brush
return bRes; // CDialog::OnEraseBkgnd(pDC);
}
You need to provide a message handler for the WM_ERASEBKGND message and paint the background yourself.
Put a normal button on the Resource Editor.
On the .h file of the form where you use it, declare a CMFCButton variable like m_btnRead.
In the DoDataExchange method of your form append a line
DDX_Control(pDX, IDC_BUTTON_READ, m_btnRead);
On the method where you initialize your form (OnInitDialog, Create, etc.) append a line
m_btnRead.SetFaceColor(RGB(0, 255, 255));
and now you are done!
It might sound a little strange, but I can't correctly use the Draw_Pixel() and Draw_Line() functions of SDL_Draw.h
I've googled and people state: It's very simple to use, but unfortunately... not for me.
I've written a very simple piece of code but it doesn't show me the pixel, I tried also with a line, but nothing as well.
The simple code is:
#include <SDL.h>
#include "SDL_draw.h"
int main(int argc, char** argv)
{
SDL_Surface* surf;
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
return -1;
}
if((surf = SDL_SetVideoMode(WIDTH, HEIGTH, BBP, FLAGS)) == NULL) {
return -1;
}
Uint32 myColor = SDL_MapRGB( surf->format, 255, 25, 23); //this is the red color
Draw_Pixel(surf, 45, 45, myColor);
Draw_Line(surf, 45, 20, 90, 100, myColor);
SDL_Quit();
return 1;
}
The x,y coordinates are just random. I'm trying to see the result with breakpoints in Visual Studio.
Can anyone tell me where I'm mistaking?
You have to update your surface by calling SDL_Flip( SDL_Surface * screen) ;
And add a delay before exiting the program, otherwise you wont see the window.
I am new to VC++ and its been a few times now, and this is the third program that does not give output even after it is build succesfully.
#include <AFXWIN.H>
#include <math.h>
#define PI 3.1415926
#define SEGMENTS 500
class CMyApp : public CWinApp {
public:
virtual BOOL InitInstance();
};
class CMainWindow : public CFrameWnd
{
public:
CMainWindow();
protected:
afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT, CPoint);
DECLARE_MESSAGE_MAP();
};
CMyApp myAPP;
BOOL CMyApp::InitInstance() {
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow(SW_MAXIMIZE);
m_pMainWnd->UpdateWindow();
return TRUE;
}
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
ON_WM_PAINT ()
END_MESSAGE_MAP ()
CMainWindow::CMainWindow() {
Create(NULL,"The Hello Application",WS_OVERLAPPEDWINDOW);
}
void CMainWindow::OnPaint() {
CRect rect;
int nWidth = rect.Width();
int nHeight = rect.Height();
CPaintDC dc (this);
CPoint aPoint[SEGMENTS];
for (int i =0; i < SEGMENTS; i++){
aPoint[i].x = ((i*nWidth)/SEGMENTS );
aPoint[i].y= (int)((nHeight/2)* (1-(sin((2*PI*i)/SEGMENTS))));
}
dc.Polyline(aPoint, SEGMENTS);
UpdateData(false);
}
The above program should give Sine curve as the output, except that I get a blank window. And I don't know why does it happen. If it helps, I am using VC++ 6.0
The problem is probably that the rectangle you use to get the width and height is not initialized. You have to get the rectangle from somewhere, see e.g. CWnd::GetClientRect.
What is the default background color of a CEdit control placed in some CPropertyPage?
What puzzles me is that the background color differs when a host of CEdit is changed. That is, if one has a dialog with a CTabCtrl in it which has CEdit, the background of a read-only CEdit is grey (I suppose it is the default one in Windows). However if a CPropertySheet and CPropertyPage is used instead of a CDialog the background of the read-only CEdit is white.
With CDialog:
And with CPropertySheet:
The code used to construct these windows:
CDialog based
// DialogWithEdit.h
#pragma once
class CDialogWithEdit : public CDialog
{
DECLARE_DYNAMIC(CDialogWithEdit)
public:
CDialogWithEdit(CWnd* pParent = NULL); // standard constructor
virtual ~CDialogWithEdit();
enum { IDD = IDD_DIALOG1 };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
private:
CEdit m_regularEdit;
CEdit m_readOnlyEdit;
};
// DialogWithEdit.cpp : implementation file
#include "stdafx.h"
#include "PropertySheetTest.h"
#include "DialogWithEdit.h"
#include "afxdialogex.h"
IMPLEMENT_DYNAMIC(CDialogWithEdit, CDialog)
CDialogWithEdit::CDialogWithEdit(CWnd* pParent /*=NULL*/)
: CDialog(CDialogWithEdit::IDD, pParent){ }
CDialogWithEdit::~CDialogWithEdit(){ }
void CDialogWithEdit::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CDialogWithEdit, CDialog)
END_MESSAGE_MAP()
BOOL CDialogWithEdit::OnInitDialog ()
{
BOOL retVal = CDialog::OnInitDialog ();
WCHAR tabStr[5] = {0};
wcscpy (tabStr, L"Tab1");
TCITEM tab1 = {0};
tab1.mask = TCIF_TEXT;
tab1.cchTextMax = 5;
tab1.pszText = tabStr;
CTabCtrl * tabCtrl = (CTabCtrl*) GetDlgItem (IDC_TAB1);
tabCtrl->InsertItem (0, &tab1);
RECT tabRc = {0};
tabCtrl->GetItemRect (0, &tabRc);
m_readOnlyEdit.Create (WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL|ES_READONLY, CRect (10, 30, 100, 50), GetDlgItem (IDC_TAB1), 5);
m_readOnlyEdit.SetWindowText (L"read only");
m_regularEdit.Create (WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL, CRect (110, 30, 200, 50), GetDlgItem (IDC_TAB1), 5+1);
m_regularEdit.SetWindowText (L"editable");
return retVal;
}
CPropertySheet based
// SheetX.h
#pragma once
#include "PageX.h"
class CSheetX : public CPropertySheet
{
DECLARE_DYNAMIC(CSheetX)
public:
CSheetX(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
CSheetX(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
virtual ~CSheetX();
protected:
DECLARE_MESSAGE_MAP()
private:
CPageX m_pageX;
};
// SheetX.cpp : implementation file
#include "stdafx.h"
#include "PropertySheetTest.h"
#include "SheetX.h"
IMPLEMENT_DYNAMIC(CSheetX, CPropertySheet)
CSheetX::CSheetX(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{ AddPage (&m_pageX); }
CSheetX::CSheetX(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{ AddPage (&m_pageX); }
CSheetX::~CSheetX() { }
BEGIN_MESSAGE_MAP(CSheetX, CPropertySheet)
END_MESSAGE_MAP()
// PaheX.h
#pragma once
class CPageX : public CPropertyPage
{
DECLARE_DYNAMIC(CPageX)
public:
CPageX();
virtual ~CPageX();
enum { IDD = IDD_PAGEX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnInitDialog ();
DECLARE_MESSAGE_MAP()
private:
CEdit m_readOnlyEdit;
CEdit m_regularEdit;
};
// PageX.cpp : implementation file
#include "stdafx.h"
#include "PropertySheetTest.h"
#include "PageX.h"
#define ID_EDITCTRL 151
IMPLEMENT_DYNAMIC(CPageX, CPropertyPage)
CPageX::CPageX()
: CPropertyPage(CPageX::IDD){ }
CPageX::~CPageX(){ }
void CPageX::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
}
BOOL CPageX::OnInitDialog ()
{
BOOL retVal = CPropertyPage::OnInitDialog ();
m_readOnlyEdit.Create (WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL|ES_READONLY, CRect (10,10,100,30), this, ID_EDITCTRL);
m_readOnlyEdit.SetWindowText (L"read only");
m_regularEdit.Create (WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL, CRect (110,10,200,30), this, ID_EDITCTRL+1);
m_regularEdit.SetWindowText (L"editable");
return retVal;
}
BEGIN_MESSAGE_MAP(CPageX, CPropertyPage)
END_MESSAGE_MAP()
I could add a workaround for the white background color by handling WM_CTLCOLORSTATIC in the CPropertyPage and returning brush of the default dialog background color. But this does not seem right to me. On the other hand msdn says that WM_CTLCOLORSTATIC is sent to the parent in order for it to specify the background color. Since the parent of the CEdit control in question is a CPropertyPage I would guess that's why it returns the white brush.
Or maybe I am doing something wrong with the CPropertyPage?
It is the default Windows behaviour. Thus one has to choose: to stick with default windows behaviour or transfer WM_CTLCOLORSTATIC message from the CPropertyPage to the CPropertySheet which returns its background color (which is grey by default). On classic theme everything works correctly because the colour of the CPropertyPage is grey.