Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: cоздание объекта класса в теле CALLBACK функции.  (Прочитано 16463 раз)
0 Пользователей и 6 Гостей смотрят эту тему.
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 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
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 19-10-2005 13:12 » 

О как все запутано. Ну ты даеш. Грабли № 22
Создаеш экземпляр класса в функции, при выходе из функции, этот экземпляр автоматически уничтожается.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 19-10-2005 13:26 » 

Значит как я и думал, спасибо Finch.
« Последнее редактирование: 19-10-2005 13:28 от nikedeforest » Записан

ещё один вопрос ...
baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #3 : 20-10-2005 17:18 » 

Используй статический объект.
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 20-10-2005 17:28 » 

Цитата
Используй статический объект.
Я пока решил использовать глобальный и создаю его в WinMain. А как лучше или как правильней - статический или глобальный?
Записан

ещё один вопрос ...
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #5 : 20-10-2005 20:18 » 

nikedeforest завтра я постараюсь накидать класс компоненты.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
acc15
Гость
« Ответ #6 : 20-10-2005 20:58 » 

static edit;

я вот чо не понимаю... какого х.. код делает в хэдере Не понял
Записан
Finch
Спокойный
Администратор

il
Offline 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
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 21-10-2005 09:56 » new

acc15, речть шла немного не о том. Но спасибо за код, он мне явно пригодится.
Записан

ещё один вопрос ...
Finch
Спокойный
Администратор

il
Offline 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
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 23-10-2005 18:10 » 

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

ещё один вопрос ...
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #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 Кб - загружено 825 раз.)
« Последнее редактирование: 24-10-2005 16:28 от nikedeforest » Записан

ещё один вопрос ...
Finch
Спокойный
Администратор

il
Offline 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
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 24-10-2005 20:39 » 

Агаб вместо wParam - Message.
Продолжение на https://forum.shelek.ru/index.php/topic,7471.msg112472.html#msg112472
Записан

ещё один вопрос ...
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines