nikedeforest
|
|
« : 19-10-2005 12:59 » |
|
Я создаю класс,в котором метод CreateControl создает окно(контрол), а деструктор это окно убивает. Объект я создаю в CallBack функции главного окна программы, потом в обработчике WM_CREATE я хочу создать окно, но происходит следующее. Сразу же после WM_CREATE вызывается деструктор моего класса и окно мое естественно убивается. Впринципе я кажется понимаю почему вызываетися деструктор (хотя был бы рад если распишите почему, вдруг я ошибаюсь), хотя по началу не ожидал такого подвоха, Меня удивило следующее, несмотря на вызов деструктороа, в обработчике других сообщений я могу использовать объект этого класса. Что же получается объект класса создается и убивается с приходом каждого сообщения, я правильно понимаю? LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { edit edit_pass; int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; TCHAR szHello[MAX_LOADSTRING]; LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message) { case WM_CREATE: edit_pass.CreateControl(hInst,hWnd); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); edit_pass.Test();
//////////////////////////////////////////////////// Файл class_edit.h class edit { private: HWND hwnd; public: edit(HINSTANCE hInst,HWND hw_parent) { CreateControl(hInst, hw_parent); }; edit(){}; ~edit() { DestroyWindow(hwnd); CloseHandle(hwnd); MessageBox(0,"Destructor_edit","destructor",MB_OK); }; //---------------- HWND get_hwnd() { return hwnd; }; //---------------- void CreateControl(HINSTANCE hInst, HWND hw_parent) { hwnd=CreateWindow("EDIT","",WS_CHILD|WS_BORDER,50,10,100,20,hw_parent,NULL,hInst,0); ShowWindow(hwnd,SW_SHOW); }; //---------------- void Test() { SetWindowText(hwnd,LPCTSTR(hwnd)); MessageBox(0,"","",0); };
};
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #1 : 19-10-2005 13:12 » |
|
О как все запутано. Ну ты даеш. Грабли № 22 Создаеш экземпляр класса в функции, при выходе из функции, этот экземпляр автоматически уничтожается.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
nikedeforest
|
|
« Ответ #2 : 19-10-2005 13:26 » |
|
Значит как я и думал, спасибо Finch.
|
|
« Последнее редактирование: 19-10-2005 13:28 от nikedeforest »
|
Записан
|
ещё один вопрос ...
|
|
|
baldr
|
|
« Ответ #3 : 20-10-2005 17:18 » |
|
Используй статический объект.
|
|
|
Записан
|
Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
|
|
|
nikedeforest
|
|
« Ответ #4 : 20-10-2005 17:28 » |
|
Используй статический объект.
Я пока решил использовать глобальный и создаю его в WinMain. А как лучше или как правильней - статический или глобальный?
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #5 : 20-10-2005 20:18 » |
|
nikedeforest завтра я постараюсь накидать класс компоненты.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
acc15
Гость
|
|
« Ответ #6 : 20-10-2005 20:58 » |
|
static edit; я вот чо не понимаю... какого х.. код делает в хэдере
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #7 : 20-10-2005 21:00 » |
|
Acc15 а по русски? Что, где и куда делает? static edit;
Это вопрос или утверждение? Ибо если это утверждение, тогда будет сушествовать всего один экземпляр не потопляемый.
|
|
« Последнее редактирование: 20-10-2005 21:03 от Finch »
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
acc15
Гость
|
|
« Ответ #8 : 21-10-2005 07:45 » |
|
если я правильно понял, то вы хотите сделать класс который бы создавал своё окно, и у вас возникла проблемма : как сделать так чтобы каллбэк функция этого окна работала с нужным экземпляром объекта короче вот как я делаю... регистрирую класс ATOM edit::RegClass() { WNDCLASS wc; wc.cbClsExtra = 0; wc.cbWndExtra = 4; wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); wc.hCursor = LoadCursor(0,IDC_ARROW); wc.hIcon = LoadIcon(0,IDI_APPLICATION); wc.hInstance = hInst; // hInst - глобальная wc.lpfnWndProc = &WndProc; wc.lpszClassName = "editX1; wc.lpszMenuName = 0; wc.style = 0; return RegisterClass(&wc); } потом создание окна Handle = CreateWindow("editX1",0,WS_CHILD|WS_VISIBLE,X,Y,Width,Height,Parent, 0,hInst,0); if (!Handle) edit::~edit(); SetWindowLong(Handle,0,(LONG) this); далее в объявлении класса нужно сделать каллбэк функцию другом(пример из моего класса) : void CorrectStr(char *str); // delete nulls from the end of string void MouseMove(MBUTTONS keyData, POINT mousePos); void MouseKeyDown(MBUTTONS keyDowned, POINT mousePos); void MouseKeyUp(MBUTTONS keyUpped, POINT mousePos); void KeybKeyDown(BYTE keyDowned); void KeybKeyUp(BYTE keyUpped); ATOM RegClass(); void UpdateMonitor(); friend LRESULT CALLBACK AmperWnd(HWND Wnd, UINT Msg, WPARAM WParam, LPARAM LParam);public: AMPER(int X,int Y,unsigned int Width,unsigned int Height, double Min, double Max, double Current, HWND Parent); AMPER(int X,int Y,BYTE Preset, HWND Parent); ~AMPER(); bool CanUser; bool CanDistanceChange; HWND Monitor; void (*OnChange)(double);Затем вот пример каллбэк функции: LRESULT CALLBACK AmperWnd(HWND Wnd, UINT Msg, WPARAM WParam, LPARAM LParam) { PAMPER pAmper=0; POINT pos; MBUTTONS mbtn=0; HDC hdc; PAINTSTRUCT ps;
pAmper = (PAMPER) GetWindowLong(Wnd,0); if (!pAmper) return DefWindowProc(Wnd,Msg,WParam,LParam);
switch (Msg) { case WM_MOUSEMOVE: pos.x = LOWORD(LParam); pos.y = HIWORD(LParam); if (WParam & MK_LBUTTON == MK_LBUTTON) mbtn |= MLEFT; if (WParam & MK_MBUTTON == MK_MBUTTON) mbtn |= MMIDDLE; if (WParam & MK_RBUTTON == MK_RBUTTON) mbtn |= MRIGHT; pAmper->MouseMove(mbtn,pos); return 0; case WM_LBUTTONDOWN: pos.x = LOWORD(LParam); pos.y = HIWORD(LParam); pAmper->MouseKeyDown(MLEFT,pos); return 0; case WM_MBUTTONDOWN: pos.x = LOWORD(LParam); pos.y = HIWORD(LParam); pAmper->MouseKeyDown(MMIDDLE,pos); return 0; case WM_RBUTTONDOWN: pos.x = LOWORD(LParam); pos.y = HIWORD(LParam); pAmper->MouseKeyDown(MRIGHT,pos); return 0; case WM_LBUTTONUP: pos.x = LOWORD(LParam); pos.y = HIWORD(LParam); pAmper->MouseKeyUp(MLEFT,pos); return 0; case WM_MBUTTONUP: pos.x = LOWORD(LParam); pos.y = HIWORD(LParam); pAmper->MouseKeyUp(MMIDDLE,pos); return 0; case WM_RBUTTONUP: pos.x = LOWORD(LParam); pos.y = HIWORD(LParam); pAmper->MouseKeyUp(MRIGHT,pos); return 0; case WM_KEYDOWN: pAmper->KeybKeyDown((BYTE) WParam); return 0; case WM_KEYUP: pAmper->KeybKeyUp((BYTE) WParam); return 0; case WM_PAINT: hdc = BeginPaint(pAmper->Handle,&ps); pAmper->Draw(hdc); EndPaint(pAmper->Handle,&ps); return 0; case WM_MOVE: pAmper->wndPos.x = LOWORD(LParam); pAmper->wndPos.y = HIWORD(LParam); return 0; case WM_SIZE: pAmper->wndSize.cx = LOWORD(LParam); pAmper->wndSize.cy = HIWORD(LParam); pAmper->UpdateDrawHelpers(); return 0; case WM_SETFOCUS: pAmper->Focused = true; pAmper->Repaint(); return 0; case WM_KILLFOCUS: pAmper->Focused = false; pAmper->Repaint(); return 0; default : return DefWindowProc(Wnd,Msg,WParam,LParam); }
} прицип прост... при создании окна мы засовываем в его доп. 4 байта указатель на наш объект... и в каллбэк восстанавливаем этот указатель, после чего всё прекрасно и главное быстро работает... Friend нужен для того чтобы каллбэк функция могла обращаться к private функциям нашего объекта... После создания объекта можешь делать его экземпляр в WinMain либо глобально (без разницы)... единственно что если в WinMain'e то из других функций/модулей ты этот класс не увидишь... так что лучше глобальный класс...
|
|
« Последнее редактирование: 20-12-2007 21:40 от Алексей1153++ »
|
Записан
|
|
|
|
nikedeforest
|
|
« Ответ #9 : 21-10-2005 09:56 » |
|
acc15, речть шла немного не о том. Но спасибо за код, он мне явно пригодится.
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #10 : 21-10-2005 23:13 » |
|
Вот моя версия кода компоненты. Конечно это еше сыровато. Надо дорабатывать: BaseKomponent.h#ifndef BASEKOMPONENT_H #define BASEKOMPONENT_H
#include <windows.h>
class BaseCompon { public: BaseCompon(HINSTANCE hInst, char *Name, HWND Parent, RECT rect); ~BaseCompon(void); bool RunWindow(DWORD st, int nCmdShow);
void GetName(char *ch, int len); void SetName(char *ch); void GetSize(POINT *point); void SetSize(POINT point); void GetPlace(POINT *point); void SetPlace(POINT *point); void SetBGColor(COLORREF col); HCURSOR GetCursorP(void); HCURSOR SetCursorP(HCURSOR Cursor); HWND GetHWND(void);
protected: virtual LRESULT WProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
virtual void OnDestroy(void); virtual bool OnCreate(CREATESTRUCT FAR* lpCreateStruct); virtual void OnPaint(HDC dc); virtual bool OnEraseBkgnd(HDC hdc); virtual void OnSize(int fwSizeType, int nWidth, int nHeight); virtual void OnMove(int xPos, int yPos); //virtual void SetDefaultPlacement(void); static char NameClass[]; HWND hWindow; HINSTANCE hIns; HWND hParent; HCURSOR hCursor; RECT WRect; DWORD Style; static BaseCompon *TempB;
private: static LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); static BaseCompon *GetData(const HWND hwnd); void SetData(const HWND hwnd); ATOM RegClass(void); void Destroy(void); bool Create(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct); void Paint(void); void WMSize(int fwSizeType, int nWidth, int nHeight); void WMMove(int xPos, int yPos);
COLORREF RGBBkGnd; HBRUSH brBkGnd; char Name[255]; static ATOM atom; };
#endif //BASEKOMPONENT_H
BaseKomponent.cpp#include "BaseKomponent.h"
// ------ BaseCompon ------------------------------------------------ char BaseCompon::NameClass[]="BaseClass"; ATOM BaseCompon::atom=0; BaseCompon *BaseCompon::TempB=NULL;
BaseCompon *BaseCompon::GetData(const HWND hwnd) { return (BaseCompon *) GetWindowLong(hwnd,GWL_USERDATA); }
void BaseCompon::SetData(const HWND hwnd) { SetWindowLong(hwnd, GWL_USERDATA, (LONG) this); }
LRESULT CALLBACK BaseCompon::WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { BaseCompon *temp=GetData(hwnd); if (temp !=NULL) return temp->WProc(hwnd,Message,wParam,lParam); else if (TempB !=NULL) return TempB->WProc(hwnd,Message,wParam,lParam); return 0; }
ATOM BaseCompon::RegClass(void) { if (atom == 0) { WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(BaseCompon *); wc.hInstance = hIns; wc.hIcon = 0; wc.hCursor = hCursor; wc.hbrBackground = 0; wc.lpszMenuName = NULL; wc.lpszClassName = NameClass; atom= RegisterClass(&wc); } return atom; }
LRESULT BaseCompon::WProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch (Message) { case WM_DESTROY: OnDestroy(); break; case WM_CREATE: return Create(hwnd, (LPCREATESTRUCT) lParam); break; case WM_PAINT: Paint(); break; case WM_ERASEBKGND: return OnEraseBkgnd((HDC) wParam); break; case WM_SIZE: WMSize(wParam, (int) LOWORD(lParam), (int) HIWORD(lParam)); break; case WM_MOVE: WMMove((int) LOWORD(lParam), (int) HIWORD(lParam)); break;
default: return DefWindowProc(hwnd, Message, wParam, lParam); } return 0; }
void BaseCompon::Destroy(void) { if (brBkGnd != NULL) DeleteObject(brBkGnd); OnDestroy(); hWindow=NULL; if (hParent == NULL) PostQuitMessage(0); }
bool BaseCompon::Create(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct) { SetData(hwnd); bool res=OnCreate(lpCreateStruct); //hWindow=hwnd; if (!res) { brBkGnd=CreateSolidBrush(RGBBkGnd); } return res; }
void BaseCompon::OnDestroy(void) { }
bool BaseCompon::OnCreate(CREATESTRUCT FAR* lpCreateStruct) { return false; }
void BaseCompon::Paint(void) { PAINTSTRUCT PaintStruct;
HDC dc = BeginPaint(hWindow,&PaintStruct); OnPaint(dc); EndPaint(hWindow, &PaintStruct); }
void BaseCompon::OnPaint(HDC dc) { }
bool BaseCompon::OnEraseBkgnd(HDC hdc) { RECT r; SetRectEmpty(&r); GetClientRect(hWindow, &r); FillRect(hdc,&r,brBkGnd); return true; }
void BaseCompon::WMSize(int fwSizeType, int nWidth, int nHeight) { WRect.right=nWidth; WRect.bottom=nHeight; OnSize(fwSizeType, nWidth, nHeight); }
void BaseCompon::OnSize(int fwSizeType, int nWidth, int nHeight) { }
void BaseCompon::WMMove(int xPos, int yPos) { WRect.left=xPos; WRect.top=yPos; OnMove(xPos, yPos); }
void BaseCompon::OnMove(int xPos, int yPos) { }
void BaseCompon::GetName(char *ch, int len) { if (ch != NULL) { int i=0; while ((i<(len-1)) && (Name[i] !=0)) ch[i++]=Name[i]; ch[i]=0; } }
void BaseCompon::SetName(char *ch) { if (ch != NULL) { int i=0; while ((i<253) && (ch[i] !=0)) Name[i++]=ch[i]; Name[i]=0; } }
void BaseCompon::GetSize(POINT *point) { if (point != NULL) { point->x=WRect.right; point->y=WRect.bottom; } }
void BaseCompon::SetSize(POINT point) { WRect.right=point.x; WRect.bottom=point.y; SetWindowPos(hWindow,NULL,0,0,WRect.right,WRect.bottom, SWP_NOMOVE | SWP_NOZORDER);
}
void BaseCompon::GetPlace(POINT *point) { if (point != NULL) { point->x=WRect.left; point->y=WRect.top; } }
void BaseCompon::SetPlace(POINT *point) { WRect.left=point->x; WRect.top=point->y; SetWindowPos(hWindow,NULL,WRect.left,WRect.top,0,0, SWP_NOSIZE | SWP_NOZORDER); }
HWND BaseCompon::GetHWND(void) { return hWindow; }
HCURSOR BaseCompon::GetCursorP(void) { return hCursor; }
HCURSOR BaseCompon::SetCursorP(HCURSOR Cursor) { HCURSOR res=hCursor; hCursor=Cursor; SetClassLong(hWindow, GCL_HCURSOR, (LONG) hCursor); return res; }
BaseCompon::BaseCompon(HINSTANCE hInst, char *Name, HWND Parent, RECT rect) { hCursor=LoadCursor(NULL, IDC_ARROW); hParent=Parent; SetName(Name); hIns=hInst; WRect.bottom=rect.bottom; WRect.left=rect.left; WRect.right=rect.right; WRect.top=rect.top; RegClass(); brBkGnd=NULL; SetBGColor(RGB(192,192,254)); hWindow =NULL; Style=0;
}
BaseCompon::~BaseCompon(void) { if (hWindow !=NULL) SendMessage(hWindow,WM_CLOSE, 0, 0); }
bool BaseCompon::RunWindow(DWORD St, int nCmdShow) {
if (hWindow !=NULL) SendMessage(hWindow,WM_CLOSE, 0, 0); Style=St; TempB=this; hWindow=CreateWindow(NameClass, Name, Style, WRect.left, WRect.top, WRect.right, WRect.bottom, hParent, NULL,hIns, NULL); TempB=NULL; int err=GetLastError(); if (hWindow != NULL) { ShowWindow(hWindow, nCmdShow); UpdateWindow(hWindow); }
return (hWindow !=NULL); }
void BaseCompon::SetBGColor(COLORREF col) { RGBBkGnd=col; if (brBkGnd != NULL) DeleteObject(brBkGnd); brBkGnd=CreateSolidBrush(RGBBkGnd); UpdateWindow(hWindow);
}
Ее применение: Main.cpp#include <windows.h> #include "BaseKomponent.h"
WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR CmdParam, int nCmdShow)
{ RECT rect; rect.left=0; rect.right=100; rect.top=0; rect.bottom=100; BaseCompon *Base= new BaseCompon(hInst, "My Menu", NULL, rect); if (Base->RunWindow(WS_OVERLAPPEDWINDOW, SW_SHOW)) { MSG Msg; while (GetMessage(&Msg,NULL,0,0)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } delete Base; return Msg.wParam; } else return 0; }
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
nikedeforest
|
|
« Ответ #11 : 23-10-2005 18:10 » |
|
Finch, спасибо за код. Вчера пробовал создать по твоему образу и подобию (конечно с меньшим размахом), пока ожидаемого эффекта не достигнул (не происходит реакция на сообщения в едите, т.е. я печатал в нем и все такое, а мой обработчик никаких действий не выполнял), сейчас сам разбираюсь, если что, то позже спрошу.
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
nikedeforest
|
|
« Ответ #12 : 24-10-2005 16:26 » |
|
Вот что у меня вышло (см. аттач). Я поясню что я скинул. В теле функции обратного вызова я закоментировал MessageBox(0,"message","message",MB_OK) , которыфй вызывается при любых сообщениях для едита. Раскомментируйте его и вывалится десятко 2 окошек, кстати не бойтесь проверить с виндой ничего страшного не произойдет. Но при этом едит затемнен почему-то и не получает фокус ввода (возможно потому, что я в функции обратного вызова это не прописал). Если же убрать в функции CreateControl вызов функции SetWindowLong(hwnd, GWL_WNDPROC, (LONG) MyWndProc); то будет обычный беленький едит, но сообщений его я не получу. Но стоит отметить, что я не могу получить сообщения WM_COMMAND и прочее и от затемненного едита. Короче, чтобы вас господа не путать, скажу короче - смотрите проект, там и смотреть то не на что. Вопрос еще возник, почему едит затемненный получился. Что-то мне кажется я не то сотворил. Короче я пока не в чем не уверен, жду ваших комментариев.
|
mail.tgz (18.44 Кб - загружено 835 раз.)
|
« Последнее редактирование: 24-10-2005 16:28 от nikedeforest »
|
Записан
|
ещё один вопрос ...
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #13 : 24-10-2005 16:50 » |
|
switch(wParam){ case WM_COMMAND: MessageBox(0,"","",MB_OK); break; case WM_KEYDOWN: MessageBox(hwnd,"keydown","keydown",MB_OK); break;
Это интересно, как оно у тебя работает? В switch у тебя что стоит?
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
nikedeforest
|
|
« Ответ #14 : 24-10-2005 20:39 » |
|
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
|