Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Редактируемый List Control

9.7K
15 ноября 2008 года
SpeedShifter
67 / / 07.10.2007
Хочу сделать редактриуемый Лист Контрол в режиме Репорт.
Метод: субклассинг.
Редактируемость: дабл клик на суб-айтеме вызывает поверх него окно Эдит Бокс, Энтер нажатый в Эдите изменяет текст в лист контроле.
 
Код:
cEdit_Item = new MyEdit();
cEdit_Item->Create(WS_CHILD | ES_MULTILINE | ES_AUTOHSCROLL,CRect(0,0,0,0),this,WM_USER+254);

С Эдитом получилось.
Вопрос №1: как оловить изменение ширины столбцов в Лист Контроле?(а то сразу видно что Эдит бокс просто идет поверх Лист-а)

Вопрос №2: с Комбо Боксом хуже во-первых не работает
 
Код:
cCombo_Item->ShowWindow(SW_HIDE);

Создаю так:
 
Код:
cCombo_Item= new MySButton();                          
cCombo_Item->Create( NULL, NULL, WS_VISIBLE | WS_TABSTOP | WS_CHILD , CRect(0,0,0,0), this, WM_USER+255, 0);


во-вторых Комбо Бокс по высоте слишком большой--> хотелось бы хоть увеличить высоту строк в Лист Контроле

Вопрос №3:
по нажатию на некоторые суб-айтемы вызываю диалог открытия/сохранения файла:
Код:
CString         Open_File(BOOL* bt)
{
    TCHAR           szFile[2048]={0};
        OPENFILENAME    ofn;  
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner       = AfxGetApp()->m_pMainWnd->m_hWnd;
        ofn.lpstrFile       = szFile;
        ofn.lpstrFile[0]    = 0;
        ofn.lpstrTitle      = TEXT("Отктыть Файл!!!!!!!");
        ofn.nMaxFile        = sizeof(szFile);
        ofn.lpstrFilter     = TEXT("All\0*.*\0");
        ofn.nFilterIndex    = 1;
        ofn.lpstrFileTitle  = NULL;
        ofn.nMaxFileTitle   = 0;
        ofn.lpstrInitialDir = NULL;
        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
        *bt=GetOpenFileName(&ofn);
        return szFile;
}

-работает, НО после закрытия программы Винда (Виста) пишет шо типа какой то БАГ:
 
Код:
Windows has triggered a breakpoint in Dialog.exe.

This may be due to a corruption of the heap, which indicates a bug in Dialog.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while Dialog.exe has focus.

The output window may have more diagnostic information.


Помогите!!!
288
15 ноября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: SpeedShifter

Вопрос №1: как оловить изменение ширины столбцов в Лист Контроле?(а то сразу видно что Эдит бокс просто идет поверх Лист-а)



CListCrtl отправляет родителю следующией Notify HDN_BEGINTRACK, HDN_TRACK и HDN_ENDTRACK, когда начинается, осуществляется и заканчивается изменение размеров. Кроме того, заголовок - это тоже окно и оно является дочерним для самого ListCtrl, так что можете посмотреть какие сообщения приходят ListCtrl от заголовка в процессе перетаскивания.

Цитата: SpeedShifter

во-вторых Комбо Бокс по высоте слишком большой--> хотелось бы хоть увеличить высоту строк в Лист Контроле



ListCtrl сам определяет высоту элементов в зависимости от заданного ему шрифта. Чтобы это изменить надо либо создавать ListCtrl как OwnerDraw и обрабатывать сообщения WM_DRAWITEM, WM_MEASUREITEM, но в этом случае вся прорисовка "ложится" на вас. Либо изменить высоту самого ComboBox'а. Как это делается обсуждалось не так давно где-то в этом разделе. Поищите.

Цитата: SpeedShifter

Вопрос №3:
по нажатию на некоторые суб-айтемы вызываю диалог открытия/сохранения файла:
Код:
CString         Open_File(BOOL* bt)
{
    TCHAR           szFile[2048]={0};
        OPENFILENAME    ofn;  
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner       = AfxGetApp()->m_pMainWnd->m_hWnd;
        ofn.lpstrFile       = szFile;
        ofn.lpstrFile[0]    = 0;
        ofn.lpstrTitle      = TEXT("Отктыть Файл!!!!!!!");
        ofn.nMaxFile        = sizeof(szFile);
        ofn.lpstrFilter     = TEXT("All\0*.*\0");
        ofn.nFilterIndex    = 1;
        ofn.lpstrFileTitle  = NULL;
        ofn.nMaxFileTitle   = 0;
        ofn.lpstrInitialDir = NULL;
        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
        *bt=GetOpenFileName(&ofn);
        return szFile;
}

-работает, НО после закрытия программы Винда (Виста) пишет шо типа какой то БАГ:
 
Код:
Windows has triggered a breakpoint in Dialog.exe.

This may be due to a corruption of the heap, which indicates a bug in Dialog.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while Dialog.exe has focus.

The output window may have more diagnostic information.


Помогите!!!



Эта же функция откомпилированная в MSVS2005 и запущенная в XP работает без проблем. Но я сомневаюсь, что проблема в Vist'е. Раз возникает Heap corruption, значит скорее всего где-то неправильно работаете с указателем. Причем не факт, что именно в этой функции.

9.7K
15 ноября 2008 года
SpeedShifter
67 / / 07.10.2007
Цитата:

CListCrtl отправляет родителю следующией Notify HDN_BEGINTRACK, HDN_TRACK и HDN_ENDTRACK, когда начинается, осуществляется и заканчивается изменение размеров. Кроме того, заголовок - это тоже окно и оно является дочерним для самого ListCtrl, так что можете посмотреть какие сообщения приходят ListCtrl от заголовка в процессе перетаскивания.


Сообщение ввиде

 
Код:
ON_NOTIFY_REFLECT(HDN_TRACK, ColumnTracking)

не приходит, а ON_NOTIFY я не знаю ID-заголовка.
288
15 ноября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: SpeedShifter
Сообщение ввиде
 
Код:
ON_NOTIFY_REFLECT(HDN_TRACK, ColumnTracking)

не приходит, а ON_NOTIFY я не знаю ID-заголовка.



Как выснилось, эти оповещения приходят сначала самому ListCtrl. Так что создав свой дочерний от ListCtrl класс у меня получилось перехватить их примерно следующим способом:

Код:
//ListChild.h

#pragma once
#include "afxcmn.h"

class CListChild: public CListCtrl
{
public:
    CListChild(void);
    ~CListChild(void);
public:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnHdnEndtrack(NMHDR *pNMHDR, LRESULT *pResult);
};

....................................................................................................

//ListChild.cpp

#include "StdAfx.h"
#include "ListChild.h"

CListChild::CListChild(void)
{
}

CListChild::~CListChild(void)
{
}

BEGIN_MESSAGE_MAP(CListChild, CListCtrl)
    ON_NOTIFY(HDN_ENDTRACKA, 0, &CListChild::OnHdnEndtrack)
    ON_NOTIFY(HDN_ENDTRACKW, 0, &CListChild::OnHdnEndtrack)
END_MESSAGE_MAP()

void CListChild::OnHdnEndtrack(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
    // TODO: Add your control notification handler code here
    ::MessageBox(NULL, "OK", "OK", MB_OK);
    *pResult = 0;
}
9.7K
15 ноября 2008 года
SpeedShifter
67 / / 07.10.2007
Спасибо большое!!!:) Work
НО что это такое:
 
Код:
HDN_BEGINTRACK A
HDN_BEGINTRACK W

И почему работает именно в паре?!
Впервые вижу, MSDN такое тоже не знает?!
9.7K
15 ноября 2008 года
SpeedShifter
67 / / 07.10.2007
Еще такой вопрос, если в этом Лист Контроле я создаю дочерний Эдит
 
Код:
cEdit_Item = new MyEdit();

то надо ли, а если надо то где (в деструкторе?), ДЕЛАТЬ
 
Код:
MyList::~MyList()
{
if(bEdit_Box)
    delete(cEdit_Item);
}
288
17 ноября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: SpeedShifter
Спасибо большое!!!:) Work
НО что это такое:
 
Код:
HDN_BEGINTRACK A
HDN_BEGINTRACK W

И почему работает именно в паре?!
Впервые вижу, MSDN такое тоже не знает?!



Разница в том, определена или нет константа UNICODE. В зависимости от этого отправляются разные сообщения.

288
17 ноября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: SpeedShifter
Еще такой вопрос, если в этом Лист Контроле я создаю дочерний Эдит
 
Код:
cEdit_Item = new MyEdit();

то надо ли, а если надо то где (в деструкторе?), ДЕЛАТЬ
 
Код:
MyList::~MyList()
{
if(bEdit_Box)
    delete(cEdit_Item);
}



Да. Родитель уничтожит окно, но не уничтожит объект MyList.

26K
17 ноября 2008 года
CyBOSSeR
32 / / 07.05.2008
Цитата: SpeedShifter
Редактируемость: дабл клик на суб-айтеме вызывает поверх него окно Эдит Бокс, Энтер нажатый в Эдите изменяет текст в лист контроле.



А как именно ловите сообщение о том что нажата клавиша Enter в Edit'е?
Я уже битый час с этим мучаюсь.

9.7K
17 ноября 2008 года
SpeedShifter
67 / / 07.10.2007
1: От Combo-Box я отказался в пользу List-Box (и красивее и больше похоже на правду)
2: Удалять Эдит надо только после ОТПАДА необходимости в List-Ctrl (родитель для Эдита), т.к. создается он только один раз если тот кто инициализирует List-Ctrl возжелает что-бы какие либо столбцы редактировались в такой способ. Далее просто Эдит то прячется (SW_HIDE), либо появляется (SW_SHOW), вот и все так што проблемы лишней памяти могут быть только если неудаляя List-Ctrl пытаться его еще раз создать.

P.S. Код стал стабильным толко когда я сделал так:
 
Код:
MyList::~MyList()
{
//тут нет удаления Edit.
}


Спасибо за внимание!!


А да, а если я хочу сделать колонку состояния прогресса (50%, например как в uTorrent), то единственный выход- OWNER_DRAW ? (может есть возвожность что бы он сам отрисовал ::OnPaint(), а я просто дорисовал??)
9.7K
17 ноября 2008 года
SpeedShifter
67 / / 07.10.2007
1: От Combo-Box я отказался в пользу List-Box (и красивее и больше похоже на правду)
Цитата:

CyBOSSeR:
А как именно ловите сообщение о том что нажата клавиша Enter в Edit'е?
Я уже битый час с этим мучаюсь.


2: Делаешь суб-класс на CEdit, там обрабатываешь сообщение WM_KEYDOWN, где ловишь VK_RETURN, далее както надо родительскому окну сообщить об этом: лично я отправляю свое сообщение.

Цитата:

CyBOSSeR:
Да, нужно:
И в каждый раз когда отпадает необходимость в данном Edit'е (т.е. после нажатия клавиши Enter в нем), также необходимо очистить память, выделенную под него. А то получается, что в каждый раз когда пользователь дважды щелкает по элементу у Вас память выделяется и ни разу не очищается.


2: Удалять Эдит надо только после ОТПАДА необходимости в List-Ctrl (родитель для Эдита), т.к. создается он только один раз если тот кто инициализирует List-Ctrl возжелает что-бы какие либо столбцы редактировались в такой способ. Далее просто Эдит то прячется (SW_HIDE), либо появляется (SW_SHOW), вот и все так што проблемы лишней памяти могут быть только если неудаляя List-Ctrl пытаться его еще раз создать.

P.S. Код стал стабильным толко когда я сделал так:

 
Код:
MyList::~MyList()
{
//тут нет удаления Edit.
}


Спасибо за внимание!!


А да, а если я хочу сделать колонку состояния прогресса (50%, например как в uTorrent), то единственный выход- OWNER_DRAW ? (может есть возвожность что бы он сам отрисовал ::OnPaint(), а я просто дорисовал??)
288
17 ноября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: SpeedShifter

А да, а если я хочу сделать колонку состояния прогресса (50%, например как в uTorrent), то единственный выход- OWNER_DRAW ? (может есть возвожность что бы он сам отрисовал ::OnPaint(), а я просто дорисовал??)



Почему же? Можно. Допустим так

 
Код:
CDC *dc = list1.GetDC();
dc->LineTo(100, 100);

но при этом придется еще и обрабатывать OnPaint, чтобы знать, когда область с нарисованным вами стала недйствительным. Вообщем на мой взгляд OwnerDraw подходит для таких вещей лучше.
26K
17 ноября 2008 года
CyBOSSeR
32 / / 07.05.2008
Цитата: SpeedShifter
Делаешь суб-класс на CEdit, там обрабатываешь сообщение WM_KEYDOWN, где ловишь VK_RETURN, далее както надо родительскому окну сообщить об этом: лично я отправляю свое сообщение.


Можешь, пожалуйста выложить код сабкласса CEDit'а, а то честно говоря хочется на примере посмотреть что за зверь такой сабклассинг, ну или хотя бы статью хорошую про сабклассинг в MFC.

И еще в своей программе для определения того, что пользователь нажал клавишу Enter в CEdit'e я немного переделал функцию PreTranslateMessage, а именно:

 
Код:
BOOL COSFinalReleaseDlg::PreTranslateMessage(MSG* pMsg)
{
    if (TranslateAccelerator(*this,m_hAccel,pMsg))
        return TRUE;
    if(pMsg->message==WM_KEYDOWN&&pMsg->wParam==VK_RETURN&&GetFocus()==m_pEdit) // m_pEdit - указатель на Едитбокс
        EndEdit();                          // функция обработки завершения ввода

    return CDialog::PreTranslateMessage(pMsg);
}
9.7K
17 ноября 2008 года
SpeedShifter
67 / / 07.10.2007
Суб-классинг (если я конечно правильно его называю)- это всего лишь (не помню как это начно называется) присвоение новым классом свойств и обьктов(переменных) уже создонного классы:
 
Код:
class MyEdit : public CEdit
{
тут можно добавить свои переменные и процедуры (либо переопределить существующие)
};


На счет PreTranslate- тут не нужно достаточно
 
Код:
BEGIN_MESSAGE_MAP(MyEdit, CEdit)
    ON_WM_KEYDOWN()
END_MESSAGE_MAP()

- говорим что нам надо обработать вот это сообщение
А затем собственно обрабатываем:
 
Код:
afx_msg void    MyEdit::OnKeyDown(UINT i, UINT, UINT)
{
    if (i==VK_RETURN)
    hWnd_parent->SendMessage(WM_COMMAND, Message_Enter, NULL);
}

//hWnd_parent- указатель на CWnd- ему я сам (ручками) присваиваю значение, например:
 
Код:
cEdit_Item = new MyEdit(); //выделяем память под Эдит (cEdit_Item- указатель принадлежит родителю)
    cEdit_Item->Create(WS_CHILD | ES_MULTILINE | ES_AUTOHSCROLL,CRect(0,0,0,0),this,WM_USER+2254);
    cEdit_Item->Message_Enter=ID_EDIT_ENTER;//определенное мной сообщение
    cEdit_Item->hWnd_parent=this;                  //в принципе у CEdit есть поле, содержащее родителя.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог