zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« : 30-09-2008 09:33 » |
|
Есть HDC, на ней очнеб много разных объектов, текст, графика и т.д. Как сохранить эту HDC в BITMAP, чтобы можно было редактировать эту структуру.
Вообще цель такая: создавать водяные знаки перед посылкой на принтер.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 30-09-2008 09:50 » |
|
печатью не занимался, но мне кажется, достаточно будет, когда шлёшь на принтер, на контексте принтера просто сверху шлёпнуть знаки и всё пользоваться CDC::BOOL BitBlt(...) CDC::GetPixel() CDC::SetPixel() --------- тьфу, блин, вся я со своим MFC )) но в api есть аналогичные функции для контекста
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #2 : 30-09-2008 09:53 » |
|
достаточно будет, когда шлёшь на принтер, на контексте принтера просто сверху шлёпнуть знаки и всё Если шлепнешь, то закроешь то, что находится под печатью. SetPixel работает только если на HDC выделяемая облать известна (ее тип) но так как на Контекст можеет пойти много разных элементов, то не получается определить цвет. Для этого как раз и надо HDC преобразовать в BITMAP, чтобы цвет определить.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #3 : 30-09-2008 09:57 » |
|
всегда думал, что GetPixel спасёт в данном случае а в Bitblt - там куча опций по накладыванию битмапа. Кстати, SetPixelV работает чуточку быстрее, чем SetPixel
|
|
« Последнее редактирование: 30-09-2008 09:59 от Алексей1153++ »
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #4 : 30-09-2008 09:58 » |
|
всегда думал, что GetPixel спасёт в данном случае
Пробовал - говорит ошибку. А SetPixel работает нормально.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #5 : 30-09-2008 09:59 » |
|
я предыдущий пост правил, глянь
А что за ошибка - что пишет ?
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #6 : 30-09-2008 10:02 » |
|
Возвращает -1. А GetLastError() возвращает 0.
Но в MSDN пишут:If the pixel is outside of the current clipping region, the return value is CLR_INVALID. Это как раз -1.
Но я не могу выделить этот clipping region, потому что не знаю какие объекты на контексте.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 30-09-2008 10:05 » |
|
хм... Not all devices support GetPixel. An application should call GetDeviceCaps to determine whether a specified device supports this function.
тогда пробовай GetStockObject() GetCurrentBitmap()
|
|
« Последнее редактирование: 30-09-2008 10:07 от Алексей1153++ »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #8 : 30-09-2008 10:08 » |
|
в MFC развёрнуто так _AFXWIN_INLINE CBitmap* CDC::GetCurrentBitmap() const { ASSERT(m_hAttribDC != NULL); return CBitmap::FromHandle((HBITMAP)::GetCurrentObject(m_hAttribDC, OBJ_BITMAP)); }
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #9 : 30-09-2008 10:11 » |
|
GetCurrentBitmap()
Returns a pointer to the currently selected CBitmap object. Вернет только Bitmap, но на контексте может быть и тескст, и могут Pen'ом нарисовать и т.п.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #10 : 30-09-2008 10:14 » |
|
всё, что нарисовано, будет на битмапе. Или у тебя какой то особенный контекст, с поддержкой объектов ?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #11 : 30-09-2008 10:16 » |
|
и вапще GetPixel () точно везде -1 вернул ? А если сканировать контекст и накладывать пикселы знака только там, где не -1 вернулось ?
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #12 : 30-09-2008 10:25 » |
|
Сейчас попробовал еще раз. HBITMAP hbit = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP); BITMAP bmp; GetObject(hbit, sizeof(BITMAP), (LPVOID) &bmp);
Получилось: bmp.bmBitsPixels = 1 и вапще GetPixel () точно везде -1 вернул ? А если сканировать контекст и накладывать пикселы знака только там, где не -1 вернулось ? -1 на всем контексте. (конекст обычный)
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 30-09-2008 10:39 » |
|
Specifies the number of bits required to indicate the color of a pixel.
чёрно белый принтер ?
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #14 : 30-09-2008 10:58 » |
|
чёрно белый принтер ?
Нет.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 30-09-2008 11:04 » |
|
тогда я не знаю. Ждём опытных
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #16 : 30-09-2008 13:46 » |
|
zeo, попробуй так: создать битмап нужного размера, потом SelectObject() битмап к HDC, потом рисовать в HDC.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 01-10-2008 04:00 » |
|
наверное так и надо как раз. Только потом не забыть вернуть старый битмап в контекст
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #18 : 01-10-2008 06:31 » |
|
Попробовал - получился черный рисунок почти как Малевича. Как пишут в MSDN: The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type.
Соответсвенно происходит замена моего Битмэпа, потому что при рисовании применяются разные другие объекты.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #19 : 01-10-2008 06:37 » |
|
всё правильно! Ты же при этом старый и извлекаешь - функция его возвращает. На новом надо рисовать, выводить на печать, а потом не забыть вернуть старый взад
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #20 : 01-10-2008 06:38 » |
|
zeo, вечером мне просигналь, а лучше проект скинь, попробую на практике полапать всё. А то гадать долго можно
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #21 : 01-10-2008 06:46 » |
|
Что-то ступр на меня нашел. То есть алгоритм такой: 1. Создаем на HDC битмап по размеру контекста. 2. SelectObject для этого битмапа. 3. Если в программе вызывается например SelectObject(hdc, font), то сохранить объект, на который он ссылается (наш битмэп), и после этого вызвать SelectObject(hdc, bitmap).
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #22 : 01-10-2008 07:22 » |
|
zeo, только не создавай Compatible Bitmap - создавай того же размера, но полноценный RGB.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #23 : 01-10-2008 07:35 » |
|
при чём тут font ?
oldBMP=SelectObject(hdc, newBMP); ... ... SelectObject(hdc, oldBMP);
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #24 : 01-10-2008 08:51 » |
|
Сразу после вызова StartPage: POINT pt; pt.x = GetDeviceCaps(hdc, HORZRES); pt.y = GetDeviceCaps(hdc, VERTRES);
hb = (HBITMAP)CreateBitmap(pt.x, pt.y, 1, 24,NULL ); SelectObject ( hdc, hb );
Перед тем как вызвать EndPage: CreateBMPFile(L"e:\\1.bmp", CreateBitmapInfoStruct(hb), hb, hdc);
(Эта функция сохраняет бит-мэп в файл). Получается bmp файл 24-разрядный, но с черным цветом.
|
|
« Последнее редактирование: 01-10-2008 08:55 от zeo »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #25 : 01-10-2008 09:03 » |
|
1) а где само рисование то? 2) если этого ничего не делать, то на бумагу то выходит что нибудь ?
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #26 : 01-10-2008 09:11 » |
|
Само рисование находится между StartPage и EndPage, но там выводит другая часть программы, которая со мной не связана. Я пишу обертку для этих функций, чтобы водяные знаки выводились. Да на принтер все идет нормально. hbit = (HBITMAP) LoadImage(0, PathToBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
GetObject(hbit, sizeof(BITMAP), (LPVOID) &bm); sizeinfo = sizeof(BITMAPINFO); info = (LPBITMAPINFO) malloc(sizeinfo); info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); info->bmiHeader.biWidth = bm.bmWidth; info->bmiHeader.biHeight = bm.bmHeight; info->bmiHeader.biPlanes = 1; info->bmiHeader.biBitCount = bm.bmBitsPixel * bm.bmPlanes; info->bmiHeader.biCompression = BI_RGB; info->bmiHeader.biSizeImage = bm.bmWidthBytes * bm.bmHeight; info->bmiHeader.biXPelsPerMeter = 0; info->bmiHeader.biYPelsPerMeter = 0; info->bmiHeader.biClrUsed = 0; info->bmiHeader.biClrImportant = 0; { HBITMAP hOldBitmap; HDC hMemDC = CreateCompatibleDC(NULL); hOldBitmap = (HBITMAP) SelectObject(hMemDC, hbit); GetDIBColorTable(hMemDC, 0, 0, rgb); info->bmiColors[0] = rgb[0]; SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); } StretchDIBits(hdc, 0, 0, bm.bmWidth, bm.bmHeight, 0, 0, bm.bmWidth, bm.bmHeight, bm.bmBits, info, DIB_RGB_COLORS, SRCCOPY);
Я вывожу на принтер рисунок из файла, путь к которому указан в PathToBitmap. Но если его перед выводить, то его затирают объекты, которые вызываются во время рисования. А если выводить после - то он сам закрывает собой вывод.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #27 : 01-10-2008 09:43 » |
|
вот этот момент чем то смущает { HBITMAP hOldBitmap; HDC hMemDC = CreateCompatibleDC(NULL); hOldBitmap = (HBITMAP) SelectObject(hMemDC, hbit); GetDIBColorTable(hMemDC, 0, 0, rgb); info->bmiColors[0] = rgb[0]; SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); } StretchDIBits(hdc, 0, 0, bm.bmWidth, bm.bmHeight, 0, 0, bm.bmWidth, bm.bmHeight, bm.bmBits, info, DIB_RGB_COLORS, SRCCOPY);
зачем создавать контекст, он ведь уже есть - из StartPage ? почему всё это удаляется ДО вызова EndPage? а вообще, в мсдн такой пример есть, посмотри, может это как раз что надо // Zero and then initialize the members of a DOCINFO structure. memset( &di, 0, sizeof(DOCINFO) ); di.cbSize = sizeof(DOCINFO); di.lpszDocName = "Bitmap Printing Test"; di.lpszOutput = (LPTSTR) NULL; di.lpszDataType = (LPTSTR) NULL; di.fwType = 0; // Begin a print job by calling the StartDoc function. nError = StartDoc(pd.hDC, &di); if (nError == SP_ERROR) { errhandler("StartDoc", hwnd); goto Error; } // Inform the driver that the application is about to begin // sending data. nError = StartPage(pd.hDC); if (nError <= 0) { errhandler("StartPage", hwnd); goto Error; } // Retrieve the number of pixels-per-logical-inch in the // horizontal and vertical directions for the display upon which // the bitmap was created. These are likely the same as for // the present display, so we use those values here. hWinDC = GetDC(hWnd); fLogPelsX1 = (float) GetDeviceCaps(hWinDC, LOGPIXELSX); fLogPelsY1 = (float) GetDeviceCaps(hWindDC, LOGPIXELSY); // Retrieve the number of pixels-per-logical-inch in the // horizontal and vertical directions for the printer upon which // the bitmap will be printed. fLogPelsX2 = (float) GetDeviceCaps(pd.hDC, LOGPIXELSX); fLogPelsY2 = (float) GetDeviceCaps(pd.hDC, LOGPIXELSY); // Determine the scaling factors required to print the bitmap and // retain its original proportions. if (fLogPelsX1 > fLogPelsX2) fScaleX = (fLogPelsX1 / fLogPelsX2); else fScaleX = (fLogPelsX2 / fLogPelsX1); if (fLogPelsY1 > fLogPelsY2) fScaleY = (fLogPelsY1 / fLogPelsY2); else fScaleY = (fLogPelsY2 / fLogPelsY1); // Compute the coordinates of the upper left corner of the // centered bitmap. cWidthPels = GetDeviceCaps(pd.hDC, HORZRES); xLeft = ((cWidthPels / 2) - ((int) (((float) bmih.biWidth) * fScaleX)) / 2); cHeightPels = GetDeviceCaps(pd.hDC, VERTRES); yTop = ((cHeightPels / 2) - ((int) (((float) bmih.biHeight) * fScaleY)) / 2); // Use StretchDIBits to scale the bitmap and maintain // its original proportions (that is, if the bitmap was square // when it appeared in the application's client area, it should // also appear square on the page). if (StretchDIBits(pd.hDC, xLeft, yTop, (int) ((float) bmih.biWidth * fScaleX), (int) ((float) bmih.biHeight * fScaleY), 0, 0, bmih.biWidth, bmih.biHeight, lpBits, lpBitsInfo, iUsage, SRCCOPY) == GDI_ERROR) { errhandler("StretchDIBits Failed", hwnd); } // Retrieve the width of the string that specifies the full path // and filename for the file that contains the bitmap. GetTextExtentPoint32(pd.hDC, ofn.lpstrFile, ofn.nFileExtension + 3, &szMetric); // Compute the starting point for the text-output operation. The // string will be centered horizontally and positioned three lines // down from the top of the page. xLeft = ((cWidthPels / 2) - (szMetric.cx / 2)); yTop = (szMetric.cy * 3); // Print the path and filename for the bitmap, centered at the top // of the page. TextOut(pd.hDC, xLeft, yTop, ofn.lpstrFile, ofn.nFileExtension + 3); // Determine whether the user has pressed the Cancel button in the // AbortPrintJob dialog box; if the button has been pressed, call // the AbortDoc function. Otherwise, inform the spooler that the // page is complete. nError = EndPage(pd.hDC); if (nError <= 0) { errhandler("EndPage", hwnd); goto Error; } // Inform the driver that document has ended. nError = EndDoc(pd.hDC); if (nError <= 0) errhandler("EndDoc", hwnd); Error: // Enable the application's window. EnableWindow(hwnd, TRUE); // Remove the AbortPrintJob dialog box. DestroyWindow(hdlgCancel); // Delete the printer DC. DeleteDC(pd.hDC);
а если изображения "закрывают", как ты говоришь, то всё ок - тебе лишь надо знаки прозрачно наложить на рисунок )
|
|
|
Записан
|
|
|
|
zeo
Интересующийся
Offline
Пол:
Челябинск, Россия
|
|
« Ответ #28 : 01-10-2008 09:50 » |
|
Этот код: { HBITMAP hOldBitmap; HDC hMemDC = CreateCompatibleDC(NULL); hOldBitmap = (HBITMAP) SelectObject(hMemDC, hbit); GetDIBColorTable(hMemDC, 0, 0, rgb); info->bmiColors[0] = rgb[0]; SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); }
Только с одной целью: определить info->bmiColors[0]. Прозрачно не получается накладывать рисунок.
|
|
|
Записан
|
|
|
|
|
|