На этом шаге мы рассмотрим реализацию интерфейса Drag&Drop.
Студентка 5 курса (2009-10 уч.год) Нечаева Ольга реализовала интерфейс Drag&Drop средствами бибилиотеки OWL.
Данное приложение представляет собой программу, которая перемещает элементы одного списка в другой список с использованием правой клавиши мыши, причем если элемент взяли из первого списка, то мы можем добавить его только во второй, и если элемент взяли из второго списка, то мы можем добавить его только в первый.
Вот текст приложения:
#include <owl\applicat.h> #include <owl\window.h> #include <owl\framewin.h> #include <owl\edit.h> #include <owl\listbox.h> #include <string.h> #include <cstring.h> #include <windows.h> #include "pr76_1.rc" const int UPDATE_WINDOW1=101; const int UPDATE_WINDOW3=103; // Класс приложения. class TApp: public TApplication { public: TApp():TApplication() {} void InitMainWindow(); }; class TNewList : public TListBox { public: TNewList(TWindow *parent,int Id,int x,int y,int w,int h, TModule* module = 0):TListBox(parent,Id,x,y,w,h,0){}; protected: void EvRButtonDown (UINT modKeys,TPoint &point); void EvRButtonUp (UINT modKeys,TPoint &point); DECLARE_RESPONSE_TABLE(TNewList); }; DEFINE_RESPONSE_TABLE1(TNewList, TListBox) EV_WM_RBUTTONDOWN, EV_WM_RBUTTONUP, END_RESPONSE_TABLE; // Класс главного окна. class TWndw : public TFrameWindow { public: TWndw ( const char *title); protected: BOOL fl; char s[30]; int n,p; TNewList *listBox1; TNewList *listBox2; void SetupWindow(); void EvRButtonUp(UINT,TPoint &point); void EvMouseMove(UINT,TPoint &point); void Vibor1(); void Vibor2(); void Otp1(); void Otp2(); DECLARE_RESPONSE_TABLE(TWndw); }; DEFINE_RESPONSE_TABLE1(TWndw, TFrameWindow) EV_WM_RBUTTONUP, EV_WM_MOUSEMOVE, EV_CHILD_NOTIFY(ID_LISTBOX1,UPDATE_WINDOW1,Vibor1), EV_CHILD_NOTIFY(ID_LISTBOX2,UPDATE_WINDOW1,Vibor2), EV_CHILD_NOTIFY(ID_LISTBOX1,UPDATE_WINDOW3,Otp1), EV_CHILD_NOTIFY(ID_LISTBOX2,UPDATE_WINDOW3,Otp2), END_RESPONSE_TABLE; // Это конструктор главного окна. TWndw::TWndw( const char *title): TFrameWindow (0, title),TWindow(0,title) { // Допускает переход по клавише табуляции между // управляющими элементами. EnableKBHandler(); AssignMenu(MENU_1); // Определить размеры и расположение окна. Attr.X = 100; Attr.Y = 60; Attr.W = 600; Attr.H = 550; // Создать управляющие элементы в окне. new TStatic (this, -1, "List Box1:",30, 14, 80, 36, 10 ); listBox1 = new TNewList (this, ID_LISTBOX1, 30, 45,150, 150 ); new TStatic (this, -1, "List Box2:",250, 14, 80, 36, 10 ); listBox2 = new TNewList (this, ID_LISTBOX2, 250, 45,150, 150 ); } void TWndw::SetupWindow() { TFrameWindow::SetupWindow(); // Определить начальное состояние управляющих элементов. listBox1->AddString("Клод Моне"); listBox1->AddString("Пьер Огюст Ренуар"); listBox1->AddString("Эдгар Дега"); listBox1->AddString("Винсент Ван Гог"); listBox2->AddString("Жемчуг"); listBox2->AddString("Изумруд"); listBox2->AddString("Топаз"); listBox2->AddString("Сапфир"); listBox2->AddString("Бриллиант"); listBox1->SetSelIndex(-1); listBox2->SetSelIndex(-1); fl=false; //пока ничего не "несём" n=0; p=-1; } void TNewList::EvRButtonDown(UINT modKeys,TPoint &point) { Parent->SendNotification(Attr.Id,UPDATE_WINDOW1,HWindow); } void TNewList::EvRButtonUp(UINT modKeys,TPoint &point) { Parent->SendNotification(Attr.Id,UPDATE_WINDOW3,HWindow); } void TWndw::Vibor1() { p=listBox1->GetSelIndex(); if (p!=(-1)) // если есть выбранный элемент {listBox1->GetSelString(s,sizeof(s)); fl=true; n=1; //"взяли из первого списка" } else MessageBox("Строка не выбрана или список пуст!", "Ошибка",MB_OK|MB_ICONEXCLAMATION); } void TWndw::Vibor2() { p=listBox2->GetSelIndex(); if (p!=(-1)) // если есть выбранный элемент { listBox2->GetSelString(s,sizeof(s)); fl=true; n=2; //"взяли из второго списка" } else MessageBox("Строка не выбрана или список пуст!", "Ошибка",MB_OK|MB_ICONEXCLAMATION); } void TWndw::EvMouseMove(UINT ,TPoint &point) { const char*cursor; HINSTANCE instance; HCURSOR hCursor; if (fl==true) //если что-то "несём", то поменяем курсор { instance=NULL; cursor=IDC_WAIT; hCursor=LoadCursor(instance,cursor); SetClassWord(GCW_HCURSOR,(WORD) hCursor); } } void TWndw::Otp1() { // если "взяли" из первого списка if ((n==2)&&(fl==true)) { listBox1->AddString(s); listBox2->DeleteString(p); } fl=false; n=0; //меняем курсор на обычный const char*cursor; HINSTANCE instance; HCURSOR hCursor; instance=NULL; cursor=IDC_ARROW; hCursor=LoadCursor(instance,cursor); SetClassWord(GCW_HCURSOR,(WORD) hCursor); } void TWndw::Otp2() { // если "взяли" из первого списка if ((n==1)&&(fl==true)) {listBox2->AddString(s); listBox1->DeleteString(p); } fl=false; n=0; //меняем курсор на обычный const char*cursor; HINSTANCE instance; HCURSOR hCursor; instance=NULL; cursor=IDC_ARROW; hCursor=LoadCursor(instance,cursor); SetClassWord(GCW_HCURSOR,(WORD) hCursor); } void TWndw::EvRButtonUp(UINT,TPoint &point) { //если "не донесли" до списка if (fl==true) {fl=false; n=0; p=0; const char*cursor; HINSTANCE instance; HCURSOR hCursor; instance=NULL; cursor=IDC_ARROW; hCursor=LoadCursor(instance,cursor); SetClassWord(GCW_HCURSOR,(WORD) hCursor); } } void TApp::InitMainWindow() { SetMainWindow(new TWndw("Drag&Drop")); } int OwlMain(int,char *[]) { return TApp().Run(); }
Файл ресурсов:
#ifndef WORKSHOP_INVOKED #include "windows.h" #endif #include <owl\window.rh> #define MENU_1 100 #define ID_LISTBOX1 109 #define ID_LISTBOX2 110 #ifdef RC_INVOKED #endif
Списки имеют идентификаторы listBox1 и listBox2, присвоенные им после инициализации окна:
TWndw::TWndw( const char *title): TFrameWindow (0, title),TWindow(0,title) { // Допускает переход по клавише табуляции между // управляющими элементами. EnableKBHandler(); AssignMenu(MENU_1); // Определить размеры и расположение окна. Attr.X = 100; Attr.Y = 60; Attr.W = 600; Attr.H = 550; // Создать управляющие элементы в окне. new TStatic (this, -1, "List Box1:",30, 14, 80, 36, 10 ); listBox1 = new TNewList (this, ID_LISTBOX1, 30, 45,150, 150 ); new TStatic (this, -1, "List Box2:",250, 14, 80, 36, 10 ); listBox2 = new TNewList (this, ID_LISTBOX2, 250, 45,150, 150 ); }
После нажатия правой кнопкой мыши в области списка, происходит событие EV_WM_RBUTTONDOWN, которому сопоставлено выполнение функции EvRButtonDown(UINT modKeys,TPoint &point):
void TNewList::EvRButtonDown(UINT modKeys,TPoint &point)
{
Parent->SendNotification(Attr.Id,UPDATE_WINDOW1,HWindow);
}
Функция TWindow::SendNotification имеет следующее описание:
inline void SendNotificatin(int id, int notifyCode, HWND hCtl, UINT msg = WM_COMAND);
В нашем случае посылается сообщение:
void TWndw::Vibor1() { p=listBox1->GetSelIndex(); if (p!=(-1)) // если есть выбранный элемент {listBox1->GetSelString(s,sizeof(s)); fl=true; n=1; //"взяли из первого списка" } else MessageBox("Строка не выбрана или список пуст!", "Ошибка",MB_OK|MB_ICONEXCLAMATION); }
В той функции в переменную p запоминаем номер выбранного элемента списка, в s - сам элемент, в n - номер списка, из которого "взяли элемент", устанавливаем значение true переменной fl. С помощью этой переменной определяется, "несём" мы элемент списка (true) или нет (false).
Аналогично выглядит функция Vibor2.
Когда мы двигаем мышкой по главному окну, возникает событие EV_WM_MOUSEMOVE. Реакцией на это событие является следующая функция:
void TWndw::EvMouseMove(UINT ,TPoint &point) { const char*cursor; HINSTANCE instance; HCURSOR hCursor; if (fl==true) //если что-то "несём", то поменяем курсор { instance=NULL; cursor=IDC_WAIT; hCursor=LoadCursor(instance,cursor); SetClassWord(GCW_HCURSOR,(WORD) hCursor); } }
В этой функции мы проверяем значение переменной fl. Если её значение true, то меняем курсор; если нет, то ничего не происходит.
Если мы отпустим правую кнопку мыши на окне (т е не "донесём до списка"), то возникает событие EV_WM_RBUTTONUP и выполняется функция:
void TWndw::EvRButtonUp(UINT,TPoint &point) { //если "не донесли" до списка if (fl==true) {fl=false; n=0; p=0; const char*cursor; HINSTANCE instance; HCURSOR hCursor; instance=NULL; cursor=IDC_ARROW; hCursor=LoadCursor(instance,cursor); SetClassWord(GCW_HCURSOR,(WORD) hCursor); } }
Устанавливаем значение fl равным false, обнуляем n и p, меняем вид курсора на обычный.
Если мы отпустим правую кнопку мыши в области списка, то возникает событие EV_WM_RBUTTONUP и выполняется функция
void TNewList::EvRButtonUp(UINT modKeys,TPoint &point)
{
Parent->SendNotification(Attr.Id,UPDATE_WINDOW3,HWindow);
}
Посылается сообщение:
void TWndw::Otp1() { // если "взяли" из первого списка if ((n==2)&&(fl==true)) { listBox1->AddString(s); listBox2->DeleteString(p); } fl=false; n=0; //меняем курсор на обычный const char*cursor; HINSTANCE instance; HCURSOR hCursor; instance=NULL; cursor=IDC_ARROW; hCursor=LoadCursor(instance,cursor); SetClassWord(GCW_HCURSOR,(WORD) hCursor); }
Эта функция добавляет элемент в список, если его "взяли" в другом списке, и меняет курсор на обычный.
Результат работы приложения изображен на рисунке 1:
Рис.1. Результат работы приложения
На следующем шаге мы рассмотрим программу задания цвета.