Mouse clicks in a dialog box created from a context menu - visual-c++

I have an MFC dialog based app with a context menu. An entry in the context menu brings up a modal dialog box. But clicking the mouse anywhere in that second dialog box doesn't do anything. Bringing up the same dialog box via the main menu works great. It is like the context menu is somehow stealing the mouse clicks. The code I have that brings up the context menu is:
void Cxxx::OnContextMenu(CWnd* pWnd, CPoint ptScreen)
{
CMenu menu;
VERIFY(menu.LoadMenu(IDR_MAIN_WINDOW_RIGHT_MOUSE));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, this);
}
The code that the context menu uses to bring up the dialog box is:
void Cxxx::OnPaste()
{
CPasteDlg Dlg;
...
if (Dlg.DoModal() != IDOK){
...
}
}
The OnPaste code is the exact same api that the main menu uses, and that works fine from the main menu.
Does anyone know what I am doing wrong that is preventing the mouse from working inside that paste dialog whenever it is brought up via the context menu?
If it matters, I am using Visual Studio 11 on Win7-64 bit.
Thanks in advance for any help that you can provide.

Have you remembered to do everything correctly? I have just created a test application to show a popup menu and show a dialog based on the subsequent mouse click:
// TestDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Test.h"
#include "TestDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CTestDlg dialog
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_TEST_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CTestDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_CONTEXTMENU()
ON_COMMAND(ID_TEST_SHOWDIALOG, &CTestDlg::OnTestShowdialog)
END_MESSAGE_MAP()
// CTestDlg message handlers
BOOL CTestDlg::OnInitDialog()
{
CDialogEx::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)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
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
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::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 CTestDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTestDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CTestDlg::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
CMenu menu;
VERIFY(menu.LoadMenu(IDR_MENU1));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != nullptr);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
}
void CTestDlg::OnTestShowdialog()
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
Does this help? We don't see the rest of your code or dialog resources.

Use NM_RCLICK instead of OnConTextMenu()
BEGIN_MESSAGE_MAP(CXXX, CVIEW2)
ON_NOTIFY_REFLECT(NM_RCLICK, &CXXX::OnNMRClick)
END_MESSAGE_MAP()
VOID CXXX::OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult)
{
CPoint pt1, pt2;
GetCursorPost(&pt1);
pt2 = pt1;
//TODO: Add your code with pt2, pt1 here.
//TODO: Add your event code here.
CMenu menu;
if(menu.LoadMenu(IDR_MAIN_MENU))
{
CMenu *pMenu_sub = menu.GetSubMenu(2);
pMenu_sub->TrackPopupMenu(TPM_LEFTALIGN,pt2.x, pt2.y, this);
}
return;
}

Related

Unable to change the color of my dialog boxes in my application

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.

How to change the background properties of an mfc application

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!

Unhandled exception at 0x77f8f397 in test.exe: 0xC0000005: Access violation writing location 0x00030ff0 &&& CXX0013: Error: missing operator

I wrote a program in visual C++ to display position and velocity. It worked fine. When I extended the code to display error. Eventhough I just added from visual studio. I get the access violation error, The error in code occurs first at "CEdit" from testDLg.h. Class CEdit is produced by default in axfwin.h by visual studio in windows.
// testDlg.cpp : implementation file
//
#include "stdafx.h"
#include "test.h"
#include "testDlg.h"
//#include <timer.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#pragma comment(lib,"Mx4nt.lib")
extern "C"
{
#include "mx4nt.h"
#include "mx4dll.h"
int pstn = 0;
// The following function is not included in the DLL's header file, but
// it is included in the DLL.
NOMANGLE BYTE _stdcall r_1byte( int offset );
NOMANGLE BYTE _stdcall w_1byte( int offset, unsigned char data );
}
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CtestDlg dialog
CtestDlg::CtestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CtestDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CtestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT10, tab1);
DDX_Control(pDX, IDC_EDIT11, tab2);
DDX_Control(pDX, IDC_EDIT12, tab3);
DDX_Control(pDX, IDC_EDIT13, tab4);
DDX_Control(pDX, IDC_EDIT14, tab5);
DDX_Control(pDX, IDC_EDIT15, tab6);
DDX_Control(pDX, IDC_EDIT16, tab7);
DDX_Control(pDX, IDC_EDIT1, pos1);
DDX_Control(pDX, IDC_EDIT3, pos2);
DDX_Control(pDX, IDC_EDIT5, pos3);
DDX_Control(pDX, IDC_EDIT7, pos4);
DDX_Control(pDX, IDC_EDIT2, vel1);
DDX_Control(pDX, IDC_EDIT4, vel2);
DDX_Control(pDX, IDC_EDIT6, vel3);
DDX_Control(pDX, IDC_EDIT8, vel4);
DDX_Control(pDX, IDC_EDIT9, ferr1);
DDX_Control(pDX, IDC_EDIT17, ferr2);
DDX_Control(pDX, IDC_EDIT18, ferr3);
DDX_Control(pDX, IDC_EDIT19, ferr4);
}
BEGIN_MESSAGE_MAP(CtestDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_WM_TIMER()
END_MESSAGE_MAP()
// CtestDlg message handlers
BOOL CtestDlg::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
SetIcon(m_hIcon, FALSE); // Set small icon
clear_dspl();
reset_MX4();
SetTimer(1,50,NULL);
// TODO: Add extra initialization here
GetDlgItem(IDC_EDIT10)->SetWindowText("axis1");
GetDlgItem(IDC_EDIT11)->SetWindowText("axis2");
GetDlgItem(IDC_EDIT12)->SetWindowText("axis3");
GetDlgItem(IDC_EDIT13)->SetWindowText("axis4");
GetDlgItem(IDC_EDIT14)->SetWindowText("position");
GetDlgItem(IDC_EDIT15)->SetWindowText("velocity");
GetDlgItem(IDC_EDIT16)->SetWindowText("error");
GetDlgItem(IDC_EDIT1)->SetWindowText("");
GetDlgItem(IDC_EDIT2)->SetWindowText("");
GetDlgItem(IDC_EDIT3)->SetWindowText("");
GetDlgItem(IDC_EDIT4)->SetWindowText("");
GetDlgItem(IDC_EDIT5)->SetWindowText("");
GetDlgItem(IDC_EDIT6)->SetWindowText("");
GetDlgItem(IDC_EDIT7)->SetWindowText("");
GetDlgItem(IDC_EDIT8)->SetWindowText("");
GetDlgItem(IDC_EDIT9)->SetWindowText("");
GetDlgItem(IDC_EDIT17)->SetWindowText("");
GetDlgItem(IDC_EDIT18)->SetWindowText("");
GetDlgItem(IDC_EDIT19)->SetWindowText("");
pos_preset(1, pstn);
return TRUE; // return TRUE unless you set the focus to a control
}
void CtestDlg::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 CtestDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
/*
CString str[8];
str[0].Format("%f",pos(1));
str[1].Format("%f",pos(2));
str[2].Format("%f",pos(3));
str[3].Format("%f",pos(4));
str[4].Format("%f",vel(1));
str[5].Format("%f",vel(2));
str[6].Format("%f",vel(3));
str[7].Format("%f",vel(4));
GetDlgItem(IDC_EDIT1)->SetWindowText(str[0]);
GetDlgItem(IDC_EDIT3)->SetWindowText(str[1]);
GetDlgItem(IDC_EDIT5)->SetWindowText(str[2]);
GetDlgItem(IDC_EDIT7)->SetWindowText(str[3]);
GetDlgItem(IDC_EDIT2)->SetWindowText(str[4]);
GetDlgItem(IDC_EDIT4)->SetWindowText(str[5]);
GetDlgItem(IDC_EDIT6)->SetWindowText(str[6]);
GetDlgItem(IDC_EDIT8)->SetWindowText(str[7]);
*/
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CtestDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CtestDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
//pstn += 100;
//pos_preset(1, pstn);
maxacc(1, 1.0);
velmode(1, 1.0);
CString str[8];
str[0].Format("%f",pos(1));
str[1].Format("%f",pos(2));
str[2].Format("%f",pos(3));
str[3].Format("%f",pos(4));
str[4].Format("%f",vel(1));
str[5].Format("%f",vel(2));
str[6].Format("%f",vel(3));
str[7].Format("%f",vel(4));
str[8].Format("%f",ferr(1));
str[9].Format("%f",ferr(2));
str[10].Format("%f",ferr(3));
str[11].Format("%f",ferr(4));
GetDlgItem(IDC_EDIT1)->SetWindowText(str[0]);
GetDlgItem(IDC_EDIT3)->SetWindowText(str[1]);
GetDlgItem(IDC_EDIT5)->SetWindowText(str[2]);
GetDlgItem(IDC_EDIT7)->SetWindowText(str[3]);
GetDlgItem(IDC_EDIT2)->SetWindowText(str[4]);
GetDlgItem(IDC_EDIT4)->SetWindowText(str[5]);
GetDlgItem(IDC_EDIT6)->SetWindowText(str[6]);
GetDlgItem(IDC_EDIT8)->SetWindowText(str[7]);
GetDlgItem(IDC_EDIT9)->SetWindowText(str[8]);
GetDlgItem(IDC_EDIT17)->SetWindowText(str[9]);
GetDlgItem(IDC_EDIT18)->SetWindowText(str[10]);
GetDlgItem(IDC_EDIT19)->SetWindowText(str[11]);
//KillTimer(1);
//i = i+100;
//Invalidate();
CDialog::OnTimer(nIDEvent);
}
--
- Nandhini
www.linkedin.com/in/nandhinisudarsanan
// testDlg.h : header file
//
#pragma once
#include "afxwin.h"
// CtestDlg dialog
class CtestDlg : public CDialog
{
// Construction
public:
CtestDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_TEST_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CEdit tab1;
CEdit tab2;
CEdit tab3;
CEdit tab4;
CEdit tab5;
CEdit tab6;
CEdit tab7;
CEdit pos1;
CEdit pos2;
CEdit pos3;
CEdit pos4;
CEdit vel1;
CEdit vel2;
CEdit vel3;
CEdit vel4;
CEdit ferr1;
CEdit ferr2;
CEdit ferr3;
CEdit ferr4;
afx_msg void OnTimer(UINT nIDEvent);
};
The result I got from debugging.
NTDLL.DLL!77f8f397()
NTDLL.DLL!77fa0346()
mfc70d.dll!AfxWinMain(HINSTANCE__ * hInstance=, HINSTANCE__ * hPrevInstance=, char * lpCmdLine=, int nCmdShow=) Line 23 C++
hInstance CXX0017: Error: symbol "" not found HINSTANCE__ *
unused CXX0030: Error: expression cannot be evaluated int
hPrevInstance CXX0030: Error: expression cannot be evaluated HINSTANCE__ *
unused CXX0030: Error: expression cannot be evaluated int
lpCmdLine CXX0030: Error: expression cannot be evaluated char *
CXX0030: Error: expression cannot be evaluated char
nCmdShow CXX0030: Error: expression cannot be evaluated int
HINSTANCE__* should equal some value where as nothing has been found there. I am receiving
77F8F397 CXX0013: Error: missing operator
Need help unpacking this Thanks.
Update :
I removed unnecessary CEdits. It doesn't produce any errors. The value for velocity and error is constantly zero, eventhough I know it should not display a zero.
Use debugger!
Run your application under debugger (F5 by default in Visual Studio).
When exception will be thrown, press "Break". Application execution will be halted (debug breakpoint), and source code location of error will be shown.
If error location is out of your code (probably somewhere in library code), look at "Call Stack" window and pick topmost function that you recognize. You will jump to location in your code that caused further problems.
Look at "Autos" and "Locals" windows. Inspect values of variables, compare with values you expect. You will be able to find mistake quickly.
Happy debugging!

Does anyone know of a low level (no frameworks) example of a drag & drop, re-order-able list?

I am looking for code (any language) of a basic graphical list which can be reordered by drag and drop. So exactly this functionality http://jqueryui.com/sortable/ but written directly on the frame buffer/canvas without any frameworks (or low level 'put pixel' libraries at most) and probably not in HTML/JS (unless it's Canvas only without CSS).
The simpler the better as I will be using it in assembler and I don't want to reinvent the wheel if not needed.
heh I hate frameworks so this is easy as pie for me...
this is what I coded for my students during my lectures few years back:
http://ulozto.net/x2b7WLwJ/select-drag-drop-zip
This is the main engine code (complete project + exe is in that zip above):
//---------------------------------------------------------------------------
//--- Constants: ------------------------------------------------------------
//---------------------------------------------------------------------------
const int _select_max_l=16;
const int _select_max_ll=_select_max_l*_select_max_l;
const int _half_size=10;
const int _atoms_max=32;
//---------------------------------------------------------------------------
enum _atom_type_enum //++++
{
_atom_type_non=0,
_atom_type_kruh,
_atom_type_stvorec,
_atom_type_enum_end
};
//---------------------------------------------------------------------------
enum _editor_edit_mode_enum //****
{
_editor_edit_mode_non=0,
_editor_edit_mode_move,
_editor_edit_mode_mov,
_editor_edit_mode_add_kruh,
_editor_edit_mode_add_stvorec,
_editor_edit_mode_del,
_editor_edit_mode_enum_end
};
//---------------------------------------------------------------------------
//--- viewer: ---------------------------------------------------------------
//---------------------------------------------------------------------------
class viewer
{
public: int x0,y0;
viewer() { x0=0; y0=0; }
void world2screen(int &sx,int &sy,int wx,int wy) { sx=wx-x0; sy=wy-y0; }
void screen2world(int &wx,int &wy,int sx,int sy) { wx=sx+x0; wy=sy+y0; }
void world2screen(int &sl,int wl) { sl=wl; }
void screen2world(int &wl,int sl) { wl=sl; }
};
//---------------------------------------------------------------------------
//--- atom kruh: ------------------------------------------------------------
//---------------------------------------------------------------------------
class atom_kruh
{
public: int x,y,r; // world coordinates
TColor col0,col1,col2;
AnsiString str;
atom_kruh() { x=0; y=0; r=_half_size; str=""; col0=clBlue; col1=clAqua; col2=clWhite; }
void draw(TCanvas *scr,const viewer &view)
{
int xx,yy,rr;
view.world2screen(xx,yy,x,y);
view.world2screen(rr,r);
scr->Brush->Color=col0;
scr->Pen ->Color=col1;
scr->Font ->Color=col2;
scr->Ellipse(xx-rr,yy-rr,xx+rr,yy+rr);
scr->Brush->Style=bsClear;
xx-=scr->TextWidth(str)>>1;
yy-=scr->TextHeight(str)>>1;
scr->TextOutA(xx,yy,str);
scr->Brush->Style=bsSolid;
}
bool select(int &ll,int wx,int wy)
{
int qq,xx,yy;
xx=wx-x; xx*=xx;
yy=wy-y; yy*=yy;
qq=xx+yy;
if ((qq<=_select_max_ll)&&((qq<=ll)||(ll<0))) { ll=qq; return true; }
return false;
}
};
//---------------------------------------------------------------------------
//--- atom kruh: ------------------------------------------------------------
//---------------------------------------------------------------------------
class atom_stvorec
{
public: int x,y,r; // world coordinates
TColor col0,col1,col2;
AnsiString str;
atom_stvorec() { x=0; y=0; r=_half_size; str=""; col0=clBlue; col1=clAqua; col2=clWhite; }
void draw(TCanvas *scr,const viewer &view)
{
int xx,yy,rr;
view.world2screen(xx,yy,x,y);
view.world2screen(rr,r);
scr->Brush->Color=col0;
scr->Pen ->Color=col1;
scr->Font ->Color=col2;
scr->Rectangle(xx-rr,yy-rr,xx+rr,yy+rr);
scr->Brush->Style=bsClear;
xx-=scr->TextWidth(str)>>1;
yy-=scr->TextHeight(str)>>1;
scr->TextOutA(xx,yy,str);
scr->Brush->Style=bsSolid;
}
bool select(int &ll,int wx,int wy)
{
int qq,xx,yy;
xx=wx-x; xx*=xx;
yy=wy-y; yy*=yy;
qq=xx+yy;
if ((qq<=_select_max_ll)&&((qq<=ll)||(ll<0))) { ll=qq; return true; }
return false;
}
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
class editor
{
public: Graphics::TBitmap *bmp; // back buffer
int xs,ys;
int sel_ix,sel_tp; // actual mouse selected item
int edit_mode; // selected edit tool
viewer view; // view
bool redraw; // redraw needed?
bool locked; // edit in progress?
WORD key,key0;
int mx,my,mx0,my0;
TShiftState sh,sh0;
atom_kruh kruh[_atoms_max]; // all object lists
atom_stvorec stvorec[_atoms_max];
int kruhov;
int stvorcov;
editor();
~editor();
void resize(int _xs,int _ys); // interface with window
void draw();
void mouse(int x,int y,TShiftState s) { mx0=mx; my0=my; sh0=sh; mx=x; my=y; sh=s; edit(); }
void keys(WORD k,TShiftState s) { key0=key; sh0=sh; key=k; sh=s; edit(); }
void select(); // helper functions
void edit();
void move (bool q0,bool q1,int x,int y,int dx,int dy);
void mov (bool q0,bool q1,int x,int y,int dx,int dy);
void add_kruh (bool q0,bool q1,int x,int y,int dx,int dy);
void add_stvorec(bool q0,bool q1,int x,int y,int dx,int dy);
void del (bool q0,bool q1,int x,int y,int dx,int dy);
};
//---------------------------------------------------------------------------
editor::editor()
{
bmp=new Graphics::TBitmap;
resize(1,1);
sel_ix=-1;
sel_tp=_atom_type_non;
edit_mode=_editor_edit_mode_non;
key=0; key0=0;
mx=0; mx0=0;
my=0; my0=0;
locked=false;
kruhov=0;
stvorcov=0;
}
//---------------------------------------------------------------------------
editor::~editor()
{
delete bmp;
}
//---------------------------------------------------------------------------
void editor::resize(int _xs,int _ys)
{
bmp->Width=_xs;
bmp->Height=_ys;
xs=bmp->Width;
ys=bmp->Height;
redraw=true;
}
//---------------------------------------------------------------------------
void editor::draw()
{
int i;
if (!redraw) return;
redraw=false;
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->FillRect(Rect(0,0,xs,ys));
//++++
for (i=0;i<kruhov ;i++) kruh[i] .draw(bmp->Canvas,view);
for (i=0;i<stvorcov;i++) stvorec[i].draw(bmp->Canvas,view);
}
//---------------------------------------------------------------------------
void editor::select()
{
int i,wx,wy,ll;
int sel_tp0=sel_tp; sel_tp=_atom_type_non;
int sel_ix0=sel_ix; sel_ix=-1;
view.screen2world(wx,wy,mx,my);
//++++
ll=-1;
for (i=0;i<kruhov ;i++) if (kruh[i] .select(ll,wx,wy)) { sel_tp=_atom_type_kruh; sel_ix=i; };
for (i=0;i<stvorcov;i++) if (stvorec[i].select(ll,wx,wy)) { sel_tp=_atom_type_stvorec; sel_ix=i; };
if (sel_tp!=sel_tp0) redraw=true;
if (sel_ix!=sel_ix0) redraw=true;
}
//---------------------------------------------------------------------------
void editor::edit()
{
bool q0,q1;
int x,y,dx,dy;
x=mx; dx=mx-mx0;
y=my; dy=my-my0;
view.screen2world( x, y, x, y);
view.screen2world(dx,dx);
view.screen2world(dy,dy);
q0=sh0.Contains(ssLeft);
q1=sh .Contains(ssLeft);
if (!locked) select();
//****
if(edit_mode==_editor_edit_mode_mov) mov (q0,q1,x,y,dx,dy);
if(edit_mode==_editor_edit_mode_add_kruh) add_kruh (q0,q1,x,y,dx,dy);
if(edit_mode==_editor_edit_mode_add_stvorec)add_stvorec (q0,q1,x,y,dx,dy);
if(edit_mode==_editor_edit_mode_del) del (q0,q1,x,y,dx,dy);
q0=sh0.Contains(ssRight);
q1=sh .Contains(ssRight);
if (!locked) move(q0,q1,x,y,dx,dy);
}
//---------------------------------------------------------------------------
void editor::move (bool q0,bool q1,int x,int y,int dx,int dy)
{
if ((sel_ix>=0)&&(sel_tp!=_atom_type_non)) return;
if (q1)
{
view.x0-=dx;
view.y0-=dy;
redraw=true;
}
}
//---------------------------------------------------------------------------
void editor::mov (bool q0,bool q1,int x,int y,int dx,int dy)
{
if ((!locked)&&((sel_ix<0)||(sel_tp==_atom_type_non))) return;
locked=false;
if ((q1)||((q0)&&(!q1)))
{
//++++
if (sel_tp==_atom_type_kruh)
{
kruh[sel_ix].x=x;
kruh[sel_ix].y=y;
}
if (sel_tp==_atom_type_stvorec)
{
stvorec[sel_ix].x=x;
stvorec[sel_ix].y=y;
}
locked=true;
}
if (!q1) locked=false;
redraw=true;
}
//---------------------------------------------------------------------------
void editor::add_kruh (bool q0,bool q1,int x,int y,int dx,int dy)
{
if ((!locked)&&(sel_ix>=0)&&(sel_tp!=_atom_type_non)) return;
locked=false;
if (kruhov>=_atoms_max) return;
if ((!q0)&&( q1))
{
sel_tp=_atom_type_kruh;
sel_ix=kruhov;
kruhov++;
kruh[sel_ix].x=x;
kruh[sel_ix].y=y;
kruh[sel_ix].str=kruhov;
locked=true;
}
if (( q0)&&( q1))
{
kruh[sel_ix].x=x;
kruh[sel_ix].y=y;
locked=true;
}
if (( q0)&&(!q1))
{
kruh[sel_ix].x=x;
kruh[sel_ix].y=y;
}
if ((!q0)&&(!q1))
{
}
redraw=true;
}
//---------------------------------------------------------------------------
void editor::add_stvorec(bool q0,bool q1,int x,int y,int dx,int dy)
{
if ((!locked)&&(sel_ix>=0)&&(sel_tp!=_atom_type_non)) return;
locked=false;
if (stvorcov>=_atoms_max) return;
if ((!q0)&&( q1))
{
sel_tp=_atom_type_stvorec;
sel_ix=stvorcov;
stvorcov++;
stvorec[sel_ix].x=x;
stvorec[sel_ix].y=y;
stvorec[sel_ix].str=stvorcov;
locked=true;
}
if (( q0)&&( q1))
{
stvorec[sel_ix].x=x;
stvorec[sel_ix].y=y;
locked=true;
}
if (( q0)&&(!q1))
{
stvorec[sel_ix].x=x;
stvorec[sel_ix].y=y;
}
if ((!q0)&&(!q1))
{
}
redraw=true;
}
//---------------------------------------------------------------------------
void editor::del (bool q0,bool q1,int x,int y,int dx,int dy)
{
locked=false;
if ((sel_ix<0)||(sel_tp==_atom_type_non)) return;
if ((!q0)&&( q1))
{
//++++
if (sel_tp==_atom_type_kruh)
if (kruhov>0)
{
kruhov--;
kruh[sel_ix]=kruh[kruhov];
}
if (sel_tp==_atom_type_stvorec)
if (stvorcov>0)
{
stvorcov--;
stvorec[sel_ix]=stvorec[stvorcov];
}
sel_ix=-1;
sel_tp=_atom_type_non;
}
redraw=true;
}
//---------------------------------------------------------------------------
sorry for that its not entirely in English
kruh means circle
stvorec means square
This is code for window (BDS2006 VCL style)
//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "editor.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
editor edit;
int x0,y0;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void draw() // redraw app screen
{
edit.draw();
Form1->Canvas->Draw(x0,y0,edit.bmp);
// here just some info print outs
int dy=16,x=x0,y=y0-dy;
Form1->Canvas->Font->Color=clAqua;
Form1->Canvas->Brush->Style=bsClear;
Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("locked: %i",edit.locked));
Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("Key: %d",edit.key));
Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("sel_tp: %i",edit.sel_tp));
Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("sel_ix: %i",edit.sel_ix));
Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("kruhov: %i",edit.kruhov));
Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("stvorcov: %i",edit.stvorcov));
Form1->Canvas->Brush->Style=bsSolid;
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner) // init app
{
// select tool on app start
bt_tool_kruhClick(this);
}
//--- window events: ---------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender) { draw(); }
void __fastcall TForm1::FormResize(TObject *Sender) { x0=pan_top->Left; y0=pan_top->Height; edit.resize(ClientWidth-x0,ClientHeight-y0); draw(); }
void __fastcall TForm1::FormActivate(TObject *Sender) { draw(); }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { edit.keys(Key,Shift); draw(); }
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { edit.mouse(X-x0,Y-y0,Shift); draw(); }
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y){ edit.mouse(X-x0,Y-y0,Shift); draw(); }
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { edit.mouse(X-x0,Y-y0,Shift); draw(); }
//---------------------------------------------------------------------------
void __fastcall TForm1::bt_tool_kruhClick(TObject *Sender) // event on any tool button click
{
// select editor tool mode ...
edit.edit_mode=_editor_edit_mode_non;
if (bt_tool_kruh ->Down) edit.edit_mode=_editor_edit_mode_add_kruh;
if (bt_tool_stvorec->Down) edit.edit_mode=_editor_edit_mode_add_stvorec;
if (bt_tool_move ->Down) edit.edit_mode=_editor_edit_mode_mov;
if (bt_tool_delete ->Down) edit.edit_mode=_editor_edit_mode_del;
}
//---------------------------------------------------------------------------
Window has only 4 tool buttons (locked together by same guid so only one can be down at a time)
add circle tool
add square tool
move tool
delete tool
Everything is statically allocated for simplicity
[edit1] more info
create gfx object data type/class (atom_xxxx)
it should hold the size,position,shape of visual gfx representation of object. Add connection variables (object type and object index to what it should be connected). Add the real object/data inside
object ID
I am using int tp,ix;
tp means type of object
ix means index in list of object of type tp
editor engine
this should be also class or set of variables and functions. It should hold the whole edited world (lists of objects):
visualization variables like screen/backbufer bitmap or rendering context, mouse position, selection list
add functions/events like onmouse, onkey, draw,...
add edit function it should be able to select,add,del,move (drag&drop) objects. Ideally controlled by set of command to ease up the undo/redo operation
add undo/redo
add save,load
add your desired simulation functionality
and that is all if I did not forgot something.
create Application GUI interface
so create window, add panel with buttons for each tool,menu and whatever you need. Add events for mouse,keyboard,repaint,resize,drag&drop,... My example looks like this:
Add editor edit; to it globally or as a member of it. Member option is better if you want to have MDI later. Add events interface between edit and window (the second source code).
[Notes]
++++ marks part of code where you need add changes if any atom type is added to the system
**** marks part of code where you need add changes if any edit mode is added to the system
Sorry for not add more commented code if you need clarify something comment me.
Hope it helps a little ...

Why my custom CStatic derived control does not receive WM_SIZE message?

I'm currently developing a custom control that derives from CStatic MFC class (Smart Device C++ project).
I have created the control class using VC++ MFC class wizard, selecting CStatic class as its base class. I have used Class View to add OnSize event handler for my control class (I have selected WM_SIZE message from messages list), and new OnSize method has been created by Visual Studio along with ON_WM_SIZE() statement between BEGIN_MESSAGE_MAP(...) and END_MESSAGE_MAP().
The problem is that my control does not receive WM_SIZE thus OnSize method is never called - I used MoveWindow to change size of my control - its size changes as I have seen on dialog window but WM_SIZE message is never being sent. When I send WM_SIZE through SendMessage or PostMessage function - the control OnSize method is called normally. What do I wrong? I've read MSDN docs about CStatic control and there is no information that WM_SIZE message is never sent to a static control window.
Sorry for my bad English.
For a Windows dialog based project I've tested what you describe. I receive WM_SIZE messages in the custom control after a call of MoveWindow. Can you post a few pieces of your source code, especially for the dialog class where you use your custom Static control for your test?
Update after you posted your code
Did you run this in a debugger? I'm wondering why you don't get immediately an exception when the dialog is opened because CThreatSelection::OnSize is fired as one of the first events, even before the window handle threatGrid.m_hWnd of your control exists at all. So calling threatGrid.MoveWindow in your OnSize dialog event should cause an exception when the dialog opens.
I'm not sure what you are trying to achieve but it looks that you want to resize your custom Static according to the dialog size as soon as the dialog opens:
For this a possible alternative could be: Remove CThreatSelection::OnSize and place in CThreatSelection::OnInitDialog instead:
CThreatSelection::OnInitDialog()
{
CDialog::OnInitDialog();
// ... perhaps other Init-Stuff...
CRect rect;
GetClientRect(&rect);
threatGrid.MoveWindow(0,0, rect.Width(), rect.Height(), FALSE);
return TRUE;
}
Here you can call threatGrid.MoveWindow because the Window Handle threatGrid.m_hWnd is already created in OnInitDialog.
Below is a header of my CDialog based window generated by MFC wizard
#pragma once
#include "threatgrid.h"
#define COLUMN_COUNT 4
// CThreatSelection dialog
class CThreatSelection : public CDialog
{
DECLARE_DYNAMIC(CThreatSelection)
public:
CThreatSelection(CWnd* pParent = NULL); // standard constructor
virtual ~CThreatSelection();
// Dialog Data
enum { IDD = IDD_THSELECT };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
private:
public:
// My custom cotrol field
CThreatGrid threatGrid;
afx_msg void OnSize(UINT nType, int cx, int cy);
};
Here is te body:
// ThreatSelection.cpp : implementation file
//
#include "stdafx.h"
#include "SpeedNotifyNative.h"
#include "ThreatSelection.h"
// CThreatSelection dialog
IMPLEMENT_DYNAMIC(CThreatSelection, CDialog)
CThreatSelection::CThreatSelection(CWnd* pParent /*=NULL*/)
: CDialog(CThreatSelection::IDD, pParent)
, threatGrid(theApp.imaging, 3)
{
}
CThreatSelection::~CThreatSelection()
{
}
void CThreatSelection::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_THGRID, threatGrid);
}
BEGIN_MESSAGE_MAP(CThreatSelection, CDialog)
ON_WM_SIZE()
END_MESSAGE_MAP()
// CThreatSelection message handlers
BOOL CThreatSelection::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CThreatSelection::OnSize(UINT nType, int cx, int cy)
{
threatGrid.MoveWindow(0,0, cx, cy, FALSE);
//threatGrid.SizeChanged(cx,cy); I use it normally because no WM_SIZE is sent to threatGrid
CDialog::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
}
...And my custom control header:
#pragma once
#include "atltypes.h"
#include "GridIcon.h"
// CThreatGrid
class ImagingSystem;
class CThreatGrid : public CStatic
{
DECLARE_DYNAMIC(CThreatGrid)
public:
CThreatGrid(ImagingSystem* imaging, int cols);
virtual ~CThreatGrid();
protected:
DECLARE_MESSAGE_MAP()
private:
// Obiekt podsystemu obrazowania
ImagingSystem* imaging;
// Ilość kolumn w siatce
int columns;
// Spacing elementów
int spacing;
public:
// Informuje kontrolkę o zmianie rozmiaru - dotychczas nie udało mi się znaleźć rozwiązania dlaczego WM_SIZE nie ejst wysyłane
void SizeChanged(int cx, int cy);
private:
// Aktualny rozmiar - śledzony niezależnie aby uniknąć niepotrzebnych przeładowań obrazków
CSize currSize;
// Lista ikon
std::vector icons;
public:
afx_msg void OnSize(UINT nType, int cx, int cy);
};
...and my custom control body:
// ThreatGrid.cpp : implementation file
//
#include "stdafx.h"
#include "SpeedNotifyNative.h"
#include "ThreatGrid.h"
// CThreatGrid
IMPLEMENT_DYNAMIC(CThreatGrid, CStatic)
CThreatGrid::CThreatGrid(ImagingSystem* imaging, int cols)
: imaging(imaging)
, columns(cols)
{
}
CThreatGrid::~CThreatGrid()
{
}
BEGIN_MESSAGE_MAP(CThreatGrid, CStatic)
ON_WM_SIZE()
END_MESSAGE_MAP()
// Informuje kontrolkę o zmianie rozmiaru - dotychczas nie udało mi się znaleźć rozwiązania dlaczego WM_SIZE nie ejst wysyłane
void CThreatGrid::SizeChanged(int cx, int cy)
{
CSize nSize(cx,cy);
if(nSize != currSize)
{
currSize = nSize;
int wspc = (int)(0.015 * cx);
int hspc = (int)(0.015 * cy);
spacing = (wspc 0 )
{
int rows = (icons.size() + columns - 1) / columns;
int width = (currSize.cx - spacing * (2 + columns - 1)) / columns;
int height = (currSize.cy - spacing * (2 + rows - 1)) / rows;
CSize size;
if ( width Calculate(i / columns, i % columns, abspoint, size, spacing);
}
}
}
}
void CThreatGrid::OnSize(UINT nType, int cx, int cy)
{
CStatic::OnSize(nType, cx, cy);
// NEVER CALLED BY SYSTEM
}

Resources