Автоматическая перерисовка уже созданного окна
Дело вот в чем: мне надо засунуть фоновую картинку в ListBox (Visual Basic) с етим проблемы тоже есть (картинка переккрывает собою Item'ы) но ето уже другая тема... Дало в том, что ListBox не перерисобывает картинку, скопированную в его контекст.
Как сделать так, чтобы он автоматически перерисовывал забитую в него картинку ?! @#$!
сообщение WM_PAINT где заново перерисовывать картинку
Отрисовывать на уже существующем окне в принципе можно, нужно только самому рисовать каждый айтемус с соответствующим куском бэграунда.
Не знаю, поможет ли это тебе, но вот пример как поставить фоновую картинку и изменить цвет шрифта в EDIT. Правда, скролбары использовать нельзя, и т.д. А вообще твоя проблема решаема, нужно использовать owner draw.
Не знаю, как на бейсике (форум то по с++( :-) )), но на с++ нужно всего лишь перерисовывать кнопку в цикле обработки сообщений. Именно в нем, а не в WM_PAINT. Это если ты записываешь рисунок в контекст... Другой вариант- регионы. Ими ты сможешь создать кнопку не только с произвольным рисунком, но и произвольного размера. Только мороки там... Но есть еще один выход- используй мфц!
может что то общее будет разберись
Как вставить растровое изображение в компонент ListBox?
Для этого необходимо установить в инспекторе объектов поле Style в lbOwnerDrawFixed, при фиксированной высоте строки, или в lbOwnerDrawVariable, при переменной, и установить собственный обработчик события для OnDrawItem. В этом обработчике и надо рисовать растровое изображение.
Пример:
Рисуются изображения размером 32*16 (размер стандартного глифа для Delphi). Очень полезно при поиске нужного изображения для кнопок!
Установить в инспекторе объектов для ListBox поле ItemHeight = 19, а поле Color = clBtnFace.
............
{ Загрузить список файлов в ListBox1 при нажатии на кнопку Load (например)}
procedure TForm1.bLoadClick(Sender: TObject);
VAR S : String;
begin
ListBox1.Clear;{чистим список}
S := '*.bmp'#0; {задаем шаблон}
ListBox1.Perform(LB_DIR, DDL_ReadWrite, Longint(@S[1])); {заполняем список}
end;
............
{Отобразить изображения и имена файлов в ListBox}
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: DrawState);
VAR
Bitmap : TBitmap;
Offset : Integer;
BMPRect: TRect;
begin
WITH (Control AS TListBox).Canvas DO BEGIN
FillRect(Rect);
Bitmap := TBitmap.Create;
Bitmap.LoadFromFile(ListBox1.Items[Index]);
Offset := 0;
IF Bitmap <> NIL THEN BEGIN
BMPRect := Bounds(Rect.Left+2, Rect.Top+2, (Rect.Bottom-Rect.Top-2)*2, Rect.Bottom-Rect.Top-2);
{StretchDraw(BMPRect, Bitmap); Можно просто нарисовать, но лучше сначала убрать фон}
BrushCopy(BMPRect,Bitmap, Bounds(0, 0, Bitmap.Width, Bitmap.Height), Bitmap.Canvas.Pixels[0, Bitmap.Height-1]);
Offset := (Rect.Bottom-Rect.Top+1)*2;
END;
TextOut(Rect.Left+Offset, Rect.Top, ListBox1.Items[Index]);
Bitmap.Free;
END;
end;
............
Данный пример работает медленно, но оптимизация, для ускорения, вызвала бы трудность в понимании общего принципа его работы.
./////////////////////////////////////////////////////////////////////////////////
в цикле обработки сообщений. Именно в нем, а не в WM_PAINT-это как?
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
OnPaint(); //- перерисовываем пока работает наша программа.
}
Но такой подход СУПЕР неэффективен. Я приведу пример для Edit. Для ListBox все так же.
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include "resource.h"
HBRUSH hbr;
bool Init()
{
HBITMAP hbmLogo = LoadBitmap(GetModuleHandle(0), MAKEINTRESOURCE (IDB_BITMAP1));
if(hbr) DeleteObject(hbr);
hbr = CreatePatternBrush(hbmLogo); // Вся фишка в этой строке
DeleteObject(hbmLogo);
return 1;
}
BOOL OnCtlColor(HDC dc, HWND hWnd)
{
COLORREF cr = RGB(0xA0, 0, 0);
BOOL mode = TRANSPARENT;
SetBkMode(dc, mode);
SetTextColor(dc, cr);
return (BOOL)hbr;
}
void Dlg_Close(HWND hwnd)
{
EndDialog(hwnd, 0);
}
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
Init();
return true;
}
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case IDC_BUTTON1:
{
exit(0);
break;
}
default: break;
}
}
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
HANDLE_MSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
HANDLE_MSG(hwnd, WM_COMMAND, Dlg_OnCommand);
HANDLE_MSG(hwnd, WM_CLOSE, Dlg_Close);
case WM_CTLCOLOREDIT: return OnCtlColor((HDC)wParam, (HWND)lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), NULL, Dlg_Proc);
return 0;
}
Такой подход уже когда- то публиковался на этом сайте.