Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Как сменить кисть диалогового окна?


Автор: Тутанхамец 15.1.2006, 17:07
Проблема в следующем.

Есть диалог, созданный функцией DialogBox. Хочу, чтобы он рисовался растровой кистью (то есть, которая получается из CreatePatternBrush). Пытаюсь это сделать так:

Код

... в процедуре окна диалога...

    case WM_INITDIALOG: 
        newbrush=CreatePatternBrush((HBITMAP)LoadImage(hInst, (LPCTSTR)IDB_BITMAP2,IMAGE_BITMAP,0,0,0));
        

        oldbrushlng=SetClassLong(hDlg,GCL_HBRBACKGROUND,(long)newbrush);
                                i=GetLastError();
                
        UpdateWindow(hDlg);

        MessageBox(hDlg,"dialog was init","qqqq",MB_OK);

    break;
    return TRUE;


В этом меня беспокоит:

1) Всё это не работает! smile Вместо лонга старой кисти, SetClassLong возвращает 0. Казалось бы, ошибка. Но GetLastError() тоже возвращает 0.

2) Если я изменю класс, как это отразится на диалоговых окнах других программ? Они тоже будут крашены под хохлому?

3) Нужно, чтоб изменение класса сразу же сказывалось на окне. Экспериментировал с обычным окном - изменения проявляются только после того, как сверну и разверну окно. Даже с UpdateWindow(). Хотя если изменение происходит обработчике WM_INITDIALOG, то возможно оно будет видно сразу при появлении...

Народ, у кого какие мысли?)





Автор: Fixin 15.1.2006, 17:18
1) Старый браш нужно самому бать: GetClasslong(hwnd, GCW_HBRBACKGROUND);
2) Потом InvalidateRect(hwnd, NULL, TRUE);

Автор: Тутанхамец 15.1.2006, 17:41
До вообще-то старая кисть не очень-то и нужна... Важнее засандалить в класс окна новую. smile

Попробовал с InvalidateRect. Да, если окно обычное (не диалоговое), то всё рулит. Изменения возникают сразу же. Спасибо. Однако, диалоговое как было, так и осталось. Вот кусок процедуры диалогового окна:

Код

BOOL CALLBACK DlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam){
    HBRUSH newbrush;
    long oldbrushlng;

    switch(Msg){
    case WM_INITDIALOG: 
                    
        oldbrushlng=GetClassLong(hDlg,GCL_HBRBACKGROUND);
        newbrush=CreatePatternBrush((HBITMAP)LoadImage(hInst, (LPCTSTR)IDB_BITMAP2,IMAGE_BITMAP,0,0,0));
        
        SetClassLong(hDlg, GCL_HBRBACKGROUND, (long)newbrush);

//UpdateWindow(hDlg);        

InvalidateRect(hDlg,NULL,TRUE);


    return TRUE;



Наличие или отсутствие UpdateWindow влияния не оказывает.

Такое чувство, что в этом виде изменение кисти вообще не предсмотрено. smile

Это, кажется, можно обойти, если создавать диалог через DLGTEMPLATEEX. Там задается класс окна. Но больно много возни потом с созданием кнопок и прочего...

Похоже, придется окну быть некрашеным. Или можно элемент управления Picture на весь диалог...

Автор: Fixin 15.1.2006, 19:49
Цитата(Тутанхамец @ 15.1.2006, 18:41 Найти цитируемый пост)

До вообще-то старая кисть не очень-то и нужна... Важнее засандалить в класс окна новую. smile
Ну ты даешь! Старый браш надо обязательно возвращать на место, а созанный - удалять.
Блин! У тебя же диалог!
Код

BOOL CALLBACK DlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{    
    HBRUSH newbrush;    
    long oldbrushlng;    
    switch(Msg)
    {    
    case WM_INITDIALOG:
           newbrush=CreatePatternBrush((HBITMAP)LoadImage(hInst, (LPCTSTR)IDB_BITMAP2,IMAGE_BITMAP,0,0,0));
            return TRUE;
    case WM_CTLCOLOR:
         switch(HIWORD(lParam))
         {
                  case CTLCOLOR_DLG:
                           return newbrush;
         }
    }
    return NULL;

Добавлено @ 19:52
Тут старый браш тебя не волнует.

Автор: Тутанхамец 16.1.2006, 08:58
Yeeeaaah!! smile

Спасибо, друг! Закраска диалога через WM_CTLCOLORDLG работает в таком вот виде:

Код


BOOL CALLBACK DlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam){

    switch(Msg){
    case WM_INITDIALOG: 
    newbrush=CreatePatternBrush((HBITMAP)LoadImage(hInst, (LPCTSTR) IDB_BITMAP2,IMAGE_BITMAP,0,0,0));
//кисть глобальная. 
    return TRUE; 

case WM_CTLCOLORDLG:
      
          
  return (BOOL)newbrush;
    
case WM_CLOSE:
DeleteObject(newbrush);
EndDialog(hDlg,0);
return TRUE;

}

return FALSE;
}



А по поводу возвращения браша - я с API работаю пару недель всего. Палюсь, вероятно, на туфте. Вот не знаю, например, почему браши и битмапы надо возвращать на их место, а не уничтожать по отдельности. Умные люди зачем-то возвращают:

Код


// вот допустим... где-то в оконной функции...

    case WM_PAINT:

        
hBitmap=LoadImage(NULL,"eleph.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

GetObject(hBitmap, sizeof(BITMAP), &Bitmap);
        
hDC=BeginPaint(hWnd, &PaintStruct);
        
hCompatibleDC=CreateCompatibleDC(hDC);

hOldBitmap=SelectObject(hCompatibleDC,hBitmap);

GetClientRect(hWnd, &Rect);
    
StretchBlt(hDC,0,0,Rect.right, Rect.bottom, 
    hCompatibleDC,0,0,Bitmap.bmWidth, 
    Bitmap.bmHeight, SRCCOPY);

DeleteObject(hBitmap);

SelectObject(hCompatibleDC, hOldBitmap);

DeleteDC(hCompatibleDC);
                    
EndPaint(hWnd, &PaintStruct);

return 0;


Но почему нельзя сделать вот так:

Код


// после StretchBlt

DeleteDC(hCompatibleDC);

DeleteObject(hOldBitmap);
                    
EndPaint(hWnd, &PaintStruct);



Ну, или не с битмапом, а с брашью сделать так же. Что тогда? В памяти что-то останется? На глаз, вроде, работают оба варианта...

Автор: SergeCpp 16.1.2006, 09:17
Вот так я делал, когда нужно было изменить в классе что-нибудь.

Код

BOOL LifeView::PreCreateWindow( CREATESTRUCT& CreateStruct )
{
    if( !CScrollView::PreCreateWindow( CreateStruct ) )
    {
        return FALSE;
    }

static const char( * s_pLifeViewClass )( NULL );

    if( !s_pLifeViewClass )
    {
        WNDCLASSEX wcx = { sizeof( WNDCLASSEX ) };

        ::GetClassInfoEx( ::GetModuleHandle( NULL ), CreateStruct.lpszClass, &wcx );

        wcx.lpszClassName  = "LifeViewClass";
        wcx.hbrBackground  =  NULL;
        wcx.style         &= ~CS_DBLCLKS;
        wcx.style         |=  CS_OWNDC;

        ::RegisterClassEx  ( &wcx );
        s_pLifeViewClass   =  wcx.lpszClassName;
    }

    CreateStruct.lpszClass = s_pLifeViewClass;

    return TRUE;
}

Автор: Тутанхамец 16.1.2006, 10:24
Спасибо, учту. smile Хотя с ООП мне пока тяжеловато. Это ведь, насколько я понял, для MFC?

Автор: SergeCpp 16.1.2006, 12:50
Да, прога для MFC.

Если нужно, могу выслать всю — пиши ПМ или на почту.

Автор: Тутанхамец 16.1.2006, 18:25
Да нет, спасибо. Суть я понял, но пока с азами классов и MFC не разберусь, мне с нее пользы не много будет. smile

Автор: SergeCpp 17.1.2006, 08:13
А ты её в отладчике погоняешь, и понимание быстрее придёт...

Удачи!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)