« Поставить закладку » « Сделать стартовой »

« Форумы » « Блоги » « Статьи » « Новости » « Файлы » « Realcoding IRC » « Site map » « Поиск »


Главная Главная
Анонсы Анонсы
Форумы Форумы
Каталог Каталог
Поиск Поиск
Опросы Опросы
Книжный магазин Книжный магазин
Реклама на сайте
Публикации Публикации
Партнеры Партнеры
Карта Карта сайта
Рассылки Рассылки
RSS экспорт
Настройки Настройки
О нас пишут О нас пишут
Контакты Контакты
Гостевая книга Гостевая книга


ПнВтСрЧтПтСбВс
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
    Популярное
Как подключить Linux к Internet

Введение в обработку прерываний

Инструменты разработчика Android

Отображение правил и ссылочной целостности мастером наращивания

Этикетки

Краткая сводка операций

Создание собственной RSS ленты

Объект Секция

Функция AccessResource

Некоторые секреты IP-протокола




    Архив файлов



    Сообщества

    Документация

    Кто на сайте
Вы не зарегистрированы.
Имя:

Пароль:

Запомнить

Регистрация позволит Вам пользоваться дополнительными сервисами.
Сейчас на сайте:
Гостей: 177
Пользователей: 1
  • Psycho222

  • Статьи:: C/С++ :: Visual C++ :: Unbound DBGrid на VisualC++



    отправить ссылку другу версия для печати  Обсудить на форуме

    Unbound DBGrid на VisualC++



    Или о том, как не мешает иногда поразмыслить :) Часть 1.  Автор MIB

    О, сколько нам открытий чудных,
    не очень чудных и не нам…
    (автор не известен)

    Предупреждение: данная статья предназначена для прочтения лицам, достигшим совершеннолетия, без психических отклонений. Вы читаете эту статью на свой страх и риск. За возможные отрицательные последствия автор ответственности не несёт. :)

     

    И так. Думаю, многие из вас сталкивались с этим элементом управления и ломали себе голову, пытаясь заставить его работать. Я в своё время обыскал весь интернет на эту тему, но безрезультатно, везде упоминается только делфи, вижуал бейсик и тому подобное. Я против этих языков ничего не имею, но решил всё-таки как-то перенести этот элемент в VisualC++ и кое-чего достиг.

     

    Разговор пойдёт пока только о режиме Unbound.

     

    Создаём пустой диалог,  привязанный к нему класс.

    В редакторе ресурсов вставляем в диалог  элемент управления ActiveX DBGrid, нажимаем правой кнопкой, выбираем “DBGrid Control Object -> Edit”, добавляем нужное количество колонок (в принципе, эти и другие настройки можно сделать и программно, но пока воспользуемся редактором ресурсов, так меньше мороки). :)

     

    Теперь, в “обычных” свойствах DBGrid, переименовываем колонки, где необходимо – добавляем режим “button” (в этих колонках будет появляться выпадающий список). Обязательно ставим галочки в строках “Allow add new”, “Allow delete”, выбираем режим «Unbound». Всё, первичные настройки закончены.

     

    Еще раз нажимаем правой кнопкой на DBGrid, выбираем ”Class Wizard”, переходим в закладку «Member Variables», нажимаем двойным щелчком на строке, содержащей ID этого элемента (я его назвал к примеру IDD_Grid1). Появляется сообщение, что для этого элемента Wizard должен сгенерировать соответствующий класс, нажимаем «да». Создаётся класс CmsDgridCtrl. Теперь, необходимо дать название переменной, которая будет привязана к «DBGrid Control» и обмениваться с ним информацией.

     

    Возможно, вы уже доходили до этого момента,  но оказывалось, что этот класс не слишком приспособлен для работы с гридом, тем более в режиме «Unbound» :(

     

    Я решил ненмого отвлечься от VisualC и обратиться за помощью к самому гриду. Вместе с этим компонентом прилагается справочный файл: C:WindowsHelpDbgrid96.hlp. Открываю, веду поиск на тему “DBGrid unbound”. Нахожу, помимо прочего, примеры обработки четырех сообщений от самого грида:

    UnboundAddData – добавление записи

    UnboundDeleteRow – удаление записи

    UnboundWriteData – обновление отредактированной записи

    UnboundReadData – чтение данных и отображение при прокрутке или открытии грида.

     Примеры, естественно, для VBA.

     

    После небольших косметических изменений я получил скрипт VBS и сделал простенькую вэб-страничку:

     

    ВНИМАНИЕ! Если не появится грид – возможно, он прописан у вас в реестре под другим

    Clsid`ом, нужно проверить.

     

    <HTML>

    <BODY>

    <BR>

    <OBJECT CLASSID="Clsid:00028C00-0000-0000-0000-000000000046" ID=DBGrid1 height=200 width=700 >

    </OBJECT>

    <SCRIPT LANGUAGE=VBSCRIPT>

     

    Dim UserData() ‘гибкий массив для хранения данных

    Dim mTotalRows ‘счетчик строк

    Dim MAXCOLS ‘количество столбцов

     

    Sub window_OnLoad()

                    DBGrid1.AllowAddNew=True

                    DBGrid1.AllowDelete=True

                    DBGrid1.AllowUpdate=True

                    DBGrid1.DataMode=1 ‘bound=0, unbound=1

                    mTotalRows=0

                    MAXCOLS=2

    End Sub

     

     

    Sub DBGrid1_UnboundAddData(ByVal RowBuf, NewRowBookmark)

                    Dim Col

     

                    mTotalRows = mTotalRows + 1

                    ReDim Preserve UserData(MAXCOLS - 1, mTotalRows - 1) ‘ изменяем размеры массива

    ‘ с сохранением данных (счет от нуля)

                    NewRowBookmark = mTotalRows - 1

     

                    For Col = 0 To UBound(UserData, 1)

                                    If Not IsNull(RowBuf.Value(0, Col)) Then

                                                   UserData(Col, mTotalRows - 1) = RowBuf.Value(0, Col)

     

                                    Else

                                                   UserData(Col, mTotalRows - 1) = DBGrid1.Columns(Col).DefaultValue

                                    End If

                    Next

     

    End Sub

     

     

    Sub DBGrid1_UnboundReadData(ByVal RowBuf, StartLocation, ByVal ReadPriorRows)

     

                    Dim CurRow, Row, Col, RowsFetched, Incr

                      

                    If ReadPriorRows Then

                                    Incr = -1

                    Else

                                    Incr = 1

                    End If

     

                    If IsNull(StartLocation) Then

                                    If ReadPriorRows Then

                                                   CurRow = RowBuf.RowCount - 1

                                    Else

                                                   CurRow = 0

     

                                    End If

                    Else

                                    CurRow = CLng(StartLocation) + Incr

                    End If

     

                    For Row = 0 To RowBuf.RowCount - 1

                                    If CurRow < 0 Or CurRow >= mTotalRows Then Exit For

                                    For Col = 0 To UBound(UserData, 1)

                                                   RowBuf.Value(Row, Col) = UserData(Col, CurRow)

     

                                    Next

                                    RowBuf.Bookmark(Row) = CStr(CurRow)

                                    CurRow = CurRow + Incr

                                    RowsFetched = RowsFetched + 1

                    Next

                    RowBuf.RowCount = RowsFetched

     

    End Sub

     

     

    Sub DBGrid1_UnboundWriteData(ByVal RowBuf, WriteLocation)

                    Dim Col

     

                    For Col = 0 To MAXCOLS - 1

     

                                    If Not IsNull(RowBuf.Value(0, Col)) Then

                                                   UserData(Col, WriteLocation) = RowBuf.Value(0, Col)

                                    End If

                    Next

    End Sub

     

     

    Sub DBGrid1_UnboundDeleteRow(Bookmark)

                    Dim Col, Row

     

                    For Row = Bookmark + 1 To mTotalRows - 1

                                    For Col = 0 To MAXCOLS - 1

                                                   UserData(Col, Row - 1) = UserData(Col, Row)

                                    Next

                    Next

                    mTotalRows = mTotalRows - 1

    End Sub

    </SCRIPT>

    </BODY>

    </HTML>

    Комментарии к коду почти не пишу - и так более-менее понятно, что к чему :)

    Получилась вполне работоспособная страничка, правда, без выпадающих списков, но об этом – позже. После пятиминутного созерцания кода меня озарило: «В Unbound режиме грид генерирует  Unbound-сообщения, и если их правильно обработать, сделать двумерный массив для хранения данных – всё заработает!»

     

    С этой гениальной мыслью я вернулся к VisualC.

    В класс-визарде я нашел такие же сообщения для элемента IDD_Grid1, заготовил функции-обработчики для всех четырёх событий. Вот они:

     

    void CAboutDlg::OnUnboundReadDataDbgrid1(LPDISPATCH RowBuf, VARIANT FAR* StartLocation, BOOL ReadPriorRows)

    {

    }

     

    void CAboutDlg::OnUnboundWriteDataDbgrid1(LPDISPATCH RowBuf, VARIANT FAR* WriteLocation)

    {

    }

     

    void CAboutDlg::OnUnboundAddDataDbgrid1(LPDISPATCH RowBuf, VARIANT FAR* NewRowBookmark)

    {

    }

     

    void CAboutDlg::OnUnboundDeleteRowDbgrid1(VARIANT FAR* Bookmark)

    {

    }

     

    …Так-тааак :(

    Что это за LPDISPATCH такой? В справочнике MSDN читаю: при помощи этой гадости можно управлять ActiveX элементами. Но как? Искал-искал, много чего нашел, но ничего не понял. Бред :(

    И еще. RowBuf- это явно указатель на RowBuffer (это, как я понял, суб-объект грида, хранящий данные о текущей строке) В VBS всё просто: Если объект составной – пишем что-то типа Object.SubObject.Value=5. Но в классе, сгенерированном для грида - ни одного упоминания об RowBuffer, Columns, Column и т д, а ведь эти объекты входят в грид… :(

    И как выдернуть данные из этого ровбуффера?..  Перепробовал я много вариантов – без толку.

    В общем я забросил эту идею на некоторое время, но не забыл о ней.

     

    И вот однажды, роясь в MSDN по каким-то своим делам, я краем глаза заметил что-то об импортировании классов из исполняемых файлов. Оказывается, в класс-визарде есть такая штука: Нажимаем «Add  Class» - появляется выпадающий список: “New” и “From a type library”, выбираем второй. Предлагается выбрать файл *.tlb, *.olb, *.dll … Мдя…:(

     

    Но вдруг, почувствовав очередное озарение, выбираю опцию «*.*»  и ищу этот  грид (C:Windowssystem Dbgrid32.ocx) Йесс!!! Я - лучший!!! Класс-визард, как ни в чем не бывало, проглотил этот файл и выдал список классов, которые я могу спокойно подключить к своей суппер-программе. Внушительный, кстати списочек-с :)  И ровбуффер присутствует. Естественно, выделяю все классы (про запас типа), жму ОК.

     

    И так, что мы имеем: автоматичесски сформированный родной класс грида в файлах msdgridctrl.h & msdgridctrl.cpp и кучу классов, умеющих работать с гридом, но ни чем к нему не подключенных (файлы dbgrid32.h & dbgrid32.cpp)

     

    Не мудрствуя лукаво, пишу в файле msdgridctrl.h    #include “dbgrid32.h”, а в разделе public: добавляю:                 RowBuffer rb;

    Всё спокойно компилируется - очень хорошо. :)

     

    Дальше – проще. Мне в голову пришла еще одна идея: В программе может быть несколько диалогов с гридами, и делать обработку каждого грида в классе “родного” диалога – не красиво, лучше все обработки событий полностью написать в классе CmsDgridCtrl, и вызывать их из любого диалога. Иными словами:

    ………………..

    ………………..

    void MyDialog::OnUnboundWriteDataDbgrid1(LPDISPATCH RowBuf, VARIANT FAR* WriteLocation) //Это перехват сообщения грида именно в этом диалоге

    {

                    c_Grid.UnboundWrite(RowBuf,WriteLocation);

    // А это – вызов созданной вручную функции, которая находится в классе CmsDgridCtrl

    // (объект c_Grid объявлен в классе MyDialog  “CmsDgridCtrl c_Grid”)

    }

    ……………

    ……………

     Так. Теперь приступим к массиву.  Я решил использовать ColeSafeArray. Он достаточно удобный, многомерный и позволяет работать с данными VARIANT. В msdgridctrl.h  пишем:  

    public:

    COleSafeArray UserData;

     

    Теперь, в файле msdgridctrl.cpp, сразу после #includ’ов

     

    DWORD numElements[] = {1, 65535}; //20 столбцов, много-много строк,

    // в общем с запасом подготавливаем параметры для UserData

     

    Теперь, нужно вручную объявить и добавить функцию инициализации массива, да и всего грида.

     

    void CMsDgridCtrl::init(int NumColumns)

    {

                    numElements[0]=NumColumns;

                    UserData.Create(VT_VARIANT, 2, numElements);

                    mTotalRows=0;

    }

     

    Правильно. Эту функцию мы и будем вызывать из диалогов, перехватывая, например, WM_INITDIALOG

     

    А теперь – сам код:

    void CMsDgridCtrl::UnboundAdd(LPDISPATCH RowBuf, VARIANT *NewRowBookmark)

    {

                    int a,Col;

                    long index[2];

                    VARIANT value;

     

                    rb.AttachDispatch(RowBuf,FALSE);

                    for(Col=0;Col<numElements[0];Col++)

                    {

                                    index[0]=Col;

                                    index[1]=mTotalRows;

                                    value=rb.GetValue(0,Col);

                                    UserData.PutElement(index, &value);

                    }

                    mTotalRows++;//***

                    rb.DetachDispatch();

                    NewRowBookmark->vt=VT_I2;

                    NewRowBookmark->iVal=mTotalRows-1;

    }

     

    void CMsDgridCtrl::UnboundRead(LPDISPATCH RowBuf, VARIANT *StartLocation, BOOL ReadPriorRows)

    {

                    int a,Col,RowsFetched;

                    short Incr;

                    long index[2],Row;//,ubound;

                    VARIANT value;

                    VARIANT CurRow;

     

                    CurRow.vt=VT_I2;

                    rb.AttachDispatch(RowBuf,TRUE);

                    RowsFetched=0;

                    if(ReadPriorRows)

                    {

                                    Incr=-1;

                    }else

                    {

                                    Incr=1;

                    }

                    a=0;

                    if ((StartLocation->vt)==1)

                    {

                                    if(ReadPriorRows)

                                    {

                                                   CurRow.iVal=(short)rb.GetRowCount()-1;

                                                   a=0;

                                    }else

                                    {

                                                   CurRow.iVal=0;

                                                   a=0;

                                    }

                    }   

                    else

                    {

                                    CurRow.iVal=(StartLocation->iVal)+Incr;

                                    a=0;

                    }

                    a=(rb.GetRowCount())-1;

                    a=a;

                    for( Row = 0;(Row<=a);Row++)

                    {

                                    if( (CurRow.iVal<0)||(CurRow.iVal>=mTotalRows) )

                                    {

                                                   //break;

                                                   goto err;

                                    }

                                    for (Col=0;Col<numElements[0];Col++)

                                    {

                                                   index[0]=Col;

                                                   index[1]=CurRow.iVal;

                                                   UserData.GetElement(index,&value);

                                                    rb.SetValue(Row,Col,value);

                                    }

                                    rb.SetBookmark(Row,CurRow);

                                    CurRow.iVal+=Incr;

                                    RowsFetched++;

                    }

    err:

                    rb.SetRowCount(RowsFetched);

                    rb.DetachDispatch();

    }

     

    void CMsDgridCtrl::UnboundWrite(LPDISPATCH RowBuf, VARIANT *WriteLocation)

    {

                    int Col;

                    long index[2];

                    VARIANT value;

    //                AfxMessageBox("UnboundWrite",MB_OK);

                    WriteLocation->vt=VT_I2;

                    rb.AttachDispatch(RowBuf,TRUE);

                    for(Col=0;Col<numElements[0];Col++)

                    {

                                    index[0]=Col;

                                    index[1]=WriteLocation->iVal;

                                    value=rb.GetValue(0,Col);

                                    if(value.vt!=VT_NULL)

                                    {

                                                   UserData.PutElement(index, &value);

                                    }

                    }

                    rb.DetachDispatch();

    }

     

     

    void CMsDgridCtrl::UnboundDeleteRow(VARIANT *Bookmark)

    {

                    int Col, Row;

                    long index[2];

                    VARIANT value;

     

                    for(Row=(Bookmark->iVal)+1;Row<=mTotalRows-1;Row++)

                    {

                                    for(Col=0;Col<numElements[0];Col++)

                                    {

                                                   index[0]=Col;

                                                   index[1]=Row;

                                                   UserData.GetElement(index, &value);

                                                   index[0]=Col;

                                                   index[1]=Row-1;

                                                   UserData.PutElement(index, &value);

                                    }

                    }

                    mTotalRows = mTotalRows - 1;

    }

    В общем один-в-один, как наVBS :)

     

    Чуть не забыл: каждому init’у по личному destroy() :)

     

    void CMsDgridCtrl::destroy()

    {

                    mTotalRows=0;

                    UserData.Detach();

    }

     

     

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

     

    Так… статейка большая, а написано по сути мало, грид будет просто заполняться введёнными данными, осталось еще организовать удобный опрос значений строк, заполнение массива данными (к примеру из базы данных:)), опрос и изменение значений ячеек, выпадающие списки, картинки, раскраска… много чего еще…

    (подумал, и добавил в самом начале «Часть 1»  :))

     

    Продолжение следует.




    Рубрика: Visual C++




    HTML 5: пять вещей вызывающих особый интер....

    Html

    HTML 5 — это грядущее обновление гипертекстового языка разметки, основного способа создания контента для размещения его во всемирной паутине. Разработка HTML остановилась в 1999 году, на версии HTML 4.01 и с тех пор web-содержимое изменилось так, что текущие спецификации HTML перестали соответствовать сегодняшним требованиям. HTML 5 нацелен на то, чтобы увеличить функциональную совместимость HTML и соответствовать растущим требованиям разнообразного и смешанного web-контента. HTML 5 так же нацелен на устранение недостатков четвертой версии. В этой статье мы взглянем на 5 новых интересных вещей в HTML 5.


    Подробнее... | Рубрика: Html | Добавлено: 22.12.2008

    asp.net: ListView с разных сторон.

    .NET компоненты

    Элемент управления ListView был представлен в .Net Framework 3.5 как замена устаревшему GridView. Новый элемент имеет более расширенный функционал, чем его предшественник, но в тоже время лишен некоторых внутренних механизмов, что впрочем целиком следствие из расширенной универсальности ListView. Среди отличий ListView и GridView можно назвать и гибкую настройку разметки, что позволяет выводить данные не только в табличном виде, но и вообще в любом каком пожелает программист. Благодаря шаблонам ItemTemplate, EditItemTemplate, InsertItemTeplate можно настроить внешний вид при любом из состояний ListView: редактировании или выборе элемента.


    Подробнее... | Рубрика: .NET компоненты | Добавлено: 22.12.2008

    Создание кросс-таб отчета в Stimulsoft Rep....

    .NET компоненты

    Компания Стимулсофт предоставляет для разработчиков мощный набор инструментов для создания отчетов для Microsoft Visual Studio .Net 2005 и 2008; эти инструменты доступны как для Windows Forms, так и для Web Forms. Это генератор отчетов Stimulsoft Reports.Net. Генератор отчетов Stimulsoft Reports.Net имеет ряд особенностей: простая работа с дизайнером отчетов, полная поддержка экспорта в PDF, Word, Excel и многие другие форматы. Crystal Report и Microsoft Reporting Service – очень хорошие программные продукты для повседневной работы, но, если Вам необходимо создать отчеты с поддержкой кросс-табов, drill down, Ajax, штрих-кодов и возможностью подключения одновременно более одного источника данных, то Stimulsoft Reports.Net поможет Вам сэкономить массу времени. Также, данный генератор отчетов позволяет пользователям создавать свои собственные отчеты любой сложности. И все эти особенности делают Stimulsoft Reports.Net хорошим выбором в сфере программных продуктов для Business Intelligence.


    Подробнее... | Рубрика: .NET компоненты | Добавлено: 22.12.2008

    Остальные статьи:

    VivaMP - инструмент для OpenMP
    Создаем контекстно-зависимое WPF-приложени...
    Windows Vista SP2: что внутри и что важно?
    Вышел MySQL 5.1.30, первый стабильный рели...
    Тестирование параллельных программ
    Архитектура AMD64 (EM64T)
    Платформа 2009. Определяя будущее
    Windows Vista Bridge Sample Library - упра...
    Оптимизация 64-битных программ
    Подгрузка через AJAX HTML-кода, содержащег...
    Обзор нового релиза самой мощной Ajax библ...
    Firebug 1.3 и 1.4 alpha — что нового и инт...
    Релиз Microsoft Silverlight 2.0. Что новог...
    XML документация в C#
    Курсоры в MySQL 5
    Microsoft опубликовала подробности о сесси...
    Microsoft делится подробностями о том, что...
    Тестируем новый javascript от нового брауз...
    MySQL Query Cache
    Использование провайдеров компиляции в As...


    Цитата дня (все,добавить):

    Портал фрилансеров

    работа на дому


        Рубрикатор

    Программирование

    C/С++
    Обучение
    Windows API
    XAML
    Моделирование
    Паттерны
    Visual Basic 7 .NET
    WxWidgets
    Функции WinApi
    Функции С++
    Разработка под Mac OS
    Eiffel
    Visual Studio 2008
    UI дизайн
    Алгоритмы
    Конкурсные статьи
    Turbo Pascal
    Visual Studio
    CASE-средства
    Visual Studio 2005
    Без VCL
    Delphi
    Тех. документация
    Тестирование
    Software Testing
    ООП
    TCP/IP
    Google Android
    Windows Installer
    .NET Framework
    Драйвера
    C# C Sharp
    Справка
    Проектирование
    Информ. системы
    Visual Basic
    Assembler
    Оптимизация кода
    Gtk+
    Компоненты
    Реинжиниринг
    Управление проектами
    Extreeme programming
    Lotus Notes
    Алгебраическое проектирование


    Интернет технологии

    PHP
    Perl
    ASP
    WAP
    Cookies
    SSI
    CGI
    Web Servers
    VB Script
    DNS
    CSS
    XML
    Html
    Java Script
    Java2ME
    Firewall
    Flash
    .htaccess
    Apache
    VRML
    Протоколы
    Поисковые системы
    Технология JAVA
    Учебник по PHP
    Учебник по JavaScript
    Учебник по XML
    Java Q&A
    AJAX
    DHTML
    XHTML
    Dreamweaver
    Web 2.0
    Python
    Вебмастеру
    Cisco
    Ruby on Rails
    Silverlight

    Базы данных

    Access
    InterBase
    MySQL
    Oracle
    ADO .NET
    Основы SQL
    Учебник по Access 2002
    MS
    Microsoft FoxPro
    Доступ к данным
    XML в MS SQL Server 2000
    ODBC и MyODBC
    Обучение
    Caché
    DB2
    PostgresSQL
    Sybase
    Теория
    Хранилища данных
    Безопасность
    Реляционные данные
    MySQL и mSQL

    Остальное:

    Разное
    Обзоры книг
    Безопасность
    Графика и дизайн
    Юмор
    Linux
    Фракталы
    Microsoft Axapta
    Многоядерность
    Сети
    Microsoft Office
    Работа
    MS-DOS
    Криптография
    Графика и игроделание
    Новости SDK
    Системы защиты
    Учебник по AutoCad
    CVS
    Windows XP
    Windows Server 2003
    Windows Vista
    Windows 7
    Мероприятия