Добрый день. Люди добрые, мы сами не местные, помогите решить проблему. Ситуация: есть окно. На нем, для оформления, создано несколько дочерних окон, которым назначены bmp-картинки (назовем это скинами) - это все в порядке, это все работает. Проблема вот в чем: нужно несколько раз в секунду выводить на это окно текстовую информацию, не "портя" скинов. Т.е. у текста должен быть прозрачный фон. Вот тут, собственно и затык... Информации у меня мало, подскажите пожалуйста, как правильные программисты решают этот вопрос? Пытался создать дочернее окно, на нем "SetBkMode (hDC,TRANSPARENT);", но уперся в то, что не могу очистить контекст после предыдущего рисования... Пытался сперва вывести на дочернее окно кусочек фона, а потом текст, уперся в то, что DrawText не выводит (?) текст на контекст в памяти, которому уже назначена (SelectObject) картинка (что, в общем, логично). В-общем, единственное, чего я добился: сперва выводим на контекст окна кусочек фона, а потом на него же выводим текст. И в итоге получаем мерцание И попутно два вопроса: 1. Как я понял MSDN, "ValidateRect (hWnd,false);" и "BeginPaint (hWnd,PaintStruct); EndPaint (hWnd,PaintStruct);" это полностью одинаковые "вещи", т.е. обе делают одно и то же: говорят винде, что наше окно полностью перерисовалось. Нет? 2. Если я создаю контекст в памяти с помощью "CreateCompatibleDC", его по окончании нужно "ReleaseDC" или "DeleteDC"? Я-то всю жизнь делал второе, а надысь в одном исходнике увидел первое....
da-007 Если правильно установить цвета, координаты и грамотно создать DC, DrawText прекрасно отработает, не смотря на то, что DC в памяти. В вашем коде где-то есть ошибка. Да, этот метод чреват мерцанием. Не полностью одинаковые (см. описание), но оба действительно говорят винде, что продолжать слать WM_PAINT уже не надо до следующего обновления. Надо хоть иногда в msdn заглядывать!
Всем огромное спасибо, помогли. Без стеба. Quantum: "грамотно создать DC, DrawText прекрасно отработает" DrawText - работает. А вот TextOut - не хочет =( В принципе, разницы для меня нет, тока я изначально именно с TextOut работал =) "Надо хоть иногда в msdn заглядывать!" Обижаете =) Я ж все правильно делал... Именно сомнение у меня появилось, глядя на чужие исходники =)
da-007 Значит, где-то всё-таки есть ошибка. Можете выложить фрагмент кода. msdn внушает больше доверия, чем исходник Васи Пупкина.
Все, сдаюсь. Я вообще ничего не понимаю; объясните, плз, идиоту. Задача: вывести текст на окно с картинкой, используя прозрачный фон для текста. Если не сложно, загляните в ветку http://www.wasm.ru/forum/viewtopic.php?id=16291 Итого, результаты: код работает. Но как он работает, и почему - мне непонятно. Понятно лишь одно: все, что я написал - извращение. Язык С-- (гибрид Си и ассемблера), комменты вроде расставил... Cимвол "#" - это... смещение, адрес переменной, на ассемблере это "@". Проверки на ошибки убрал для удобочитаемости, в оригинале они есть, ошибок при выполнении не возникает. Создание дочернего окна: Код (Text): // ----------------------------------------------------------- WndClassEx.cbSize=sizeof(WndClassEx); WndClassEx.hInstance=hInst; WndClassEx.style=CS_HREDRAW|CS_VREDRAW; WndClassEx.lpfnWndProc=#WndProcTextClass; WndClassEx.cbWndExtra=0; WndClassEx.cbClsExtra=0; WndClassEx.hIcon=NULL; WndClassEx.hCursor=LoadCursor(0,IDC_ARROW); WndClassEx.hbrBackground=NULL; WndClassEx.lpszMenuName=0; WndClassEx.lpszClassName="My_Text"; WndClassEx.hIconSm=NULL; RegisterClassExA (#WndClassEx); hWndCpuInfo=CreateWindowEx (0,"My_Text",NULL,WS_CHILD|WS_VISIBLE,100,100,SIZE_X,SIZE_Y,hWndMain,NULL,hInst,NULL); // ----------------------------------------------------------- Обработчик WM_PAINT: // ----------------------------------------------------------- void RepaintCpuInfo () { dword hDC, hMemDC; RECT Rect; dword hBmp; // Cообщим винде что успешно отрисовались ValidateRect (hWndCpuInfo,false); // Получим контекст окошка, создадим временный контекст hDC=GetDC (hWndCpuInfo); hMemDC=CreateCompatibleDC(EAX); // Создадим битмап фона этой картинки hBmp=CreateBitmap (SIZE_X,SIZE_Y,1,32,#PsetCpuInfoBackground); // Назначить фоновую картинку нашему контексту (НАХРЕНА??) SelectObject (hMemDC,EAX); // Рисуем буковоки SelectObject (hMemDC,hFont); SetBkMode (hMemDC,TRANSPARENT); SetTextColor (hMemDC,0x101010); Rect.top=0; Rect.right=SIZE_X; Rect.left=0; Rect.bottom=SIZE_Y; DrawText (hMemDC, #CpuUsageA, -1, #Rect, DT_RIGHT); // Скопировать содержимое контекста BitBlt (hDC,0,0,SIZE_X,SIZE_Y,hMemDC,0,0,SRCCOPY); // Освободить контексты, все в порядке ReleaseDC (hWndCpuInfo,hDC); DeleteDC (hMemDC); DeleteObject (hBmp); } // ----------------------------------------------------------- Вопрос: нафига мне делать "SelectObject (hMemDC,EAX);" ("назначать" картинку контексту в памяти)? Если следующей же строчкой выбирается другой объект? Т.е. по идее, эта строчка ничего не меняет. Однако без нее ничего не работает. Кстати говоря, если думать дальше, то и CreateBitmap - не нужен... Да! Если вынести CreateBitmap в блок инициализации - тоже ни фига не работает: контекст не очищается. И по ходу - еще вопрос: SelectObject, как я понимаю, возвращает хендл предудущего выбранного объекта (П.В.О.), и перед удалением контекста надо выбрать обратно этот самый П.В.О. Вопрос: это обязательно? И в догонку - я так понимаю, можно вообще обойтись без CreateBitmap, а использовать "LBS.lbStyle=BS_HOLLOW" - "CreateBrushIndirect" - "FillRect (hMemDC....", но так у меня ничего не получилось. Ясное осознание того, что я изобретаю велосипед
Объект объекту рознь HFONT != HBITMAP. Нет. Ты же всё равно удаляешь DC. В каком таком блоке инициализации? WM_CREATE?
Дык это понятно, но я же не произвожу никаких действий с выбранным объектом? Нет, в ф-ии main, после создания главного и дочерних окон. Но я так понимаю, там затычка в другом: в связке "Select object" - "DrawText" - DrawText "портит" картинку фона... Но причины этого мне не понятны...
n0name Отображается! "Копируется" - это через BitBlt. Не согласен. В msdn написано, что DeleteDC "deletes the specified device context" и всё. Там не написано "releases the selected objects". Поэтому, даже если код работает и утечек ресурсов не наблюдается, не факт, что в следующих версиях винды не полезут глюки во всех ваших программах. Лучше лишний раз вызвать SelectObject. da-007 Мне не совсем понятен смысл фразы "контекст не очищается". Размер кистей ограничен. Поэтому не любой битмап может стать кистью. Даже если Ваш битмап помещается в кисть, нужно ещё вызывать SetBrushOrgEx, чтобы картинку не "перекашивало".
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/devcons_5g83.asp Здесь ^^^ сказано, что DeleteObject() возвратит ошибку, если GDI объект находится в HDC. Так что лучше не рисковать и всё-таки "выбрать" его назад.