开发者

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

开发者 https://www.devze.com 2022-12-23 15:56 出处:网络
I\'m currently developing a custom control that derives from CStatic MFC class (Smart Device C++ project).

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 开发者_C百科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 
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号