Почему мой пользовательский производный элемент управления CStatic не получает сообщение WM_SIZE? - PullRequest
1 голос
/ 16 марта 2010

В настоящее время я разрабатываю пользовательский элемент управления, производный от класса CStatic MFC (проект Smart Device C ++). Я создал класс управления с помощью мастера классов VC ++ MFC, выбрав класс CStatic в качестве его базового класса. Я использовал Class View для добавления обработчика события OnSize для своего класса управления (я выбрал сообщение WM_SIZE из списка сообщений), и Visual Studio создал новый метод OnSize вместе с ON_WM_SIZE () между BEGIN_MESSAGE_MAP (...) и END_MESSAGE_MAP (). Проблема в том, что мой элемент управления не получает WM_SIZE, поэтому метод OnSize никогда не вызывается - я использовал MoveWindow для изменения размера элемента управления - его размер изменяется, как я видел в диалоговом окне, но сообщение WM_SIZE никогда не отправляется. Когда я отправляю WM_SIZE через функцию SendMessage или PostMessage - метод управления OnSize вызывается нормально. Что я не прав? Я прочитал документы MSDN о контроле CStatic, и нет никакой информации о том, что сообщение WM_SIZE никогда не отправляется в окно статического контроля.

Извините за мой плохой английский.

Ответы [ 2 ]

0 голосов
/ 16 марта 2010

Ниже приведен заголовок моего окна на основе CDialog, сгенерированного мастером MFC

#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);
};

Вот тело:

// 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
}

... И мой заголовок пользовательского элемента управления:


#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);
};

... и мой пользовательский элемент управления:


// 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 голосов
/ 16 марта 2010

Для проекта на основе диалогового окна Windows я протестировал то, что вы описываете. Я получаю сообщения WM_SIZE в пользовательском элементе управления после вызова MoveWindow. Можете ли вы опубликовать несколько фрагментов исходного кода, особенно для диалогового класса, где вы используете свой собственный статический элемент управления для своего теста?

Обновление после того, как вы опубликовали свой код

Вы запускали это в отладчике? Мне интересно, почему вы не получаете немедленное исключение при открытии диалога, потому что CThreatSelection :: OnSize запускается как одно из первых событий, даже до того, как дескриптор окна threatGrid.m_hWnd вашего элемента управления вообще существует. Поэтому вызов threatGrid.MoveWindow в вашем диалоговом событии OnSize должен вызывать исключение при открытии диалога.

Я не уверен, чего вы пытаетесь достичь, но похоже, что вы хотите изменить размер своей статической статики в соответствии с размером диалога, как только диалог откроется:

Для этого возможной альтернативой может быть: Удалите CThreatSelection::OnSize и поместите вместо CThreatSelection::OnInitDialog:

CThreatSelection::OnInitDialog()
{
    CDialog::OnInitDialog();

    // ... perhaps other Init-Stuff...

    CRect rect;
    GetClientRect(&rect);

    threatGrid.MoveWindow(0,0, rect.Width(), rect.Height(), FALSE);

    return TRUE;
}

Здесь вы можете вызвать ThreatGrid.MoveWindow, поскольку дескриптор окна threatGrid.m_hWnd уже создан в OnInitDialog.

...