Je suis en train de d=E9velopper un Driver pour une imprimante. Et, je
souhaite imprimer une BITMAP.
Mais, je n'arrive pas =E0 imprimer la BITMAP en couleur, la seule chose
qui s'imprime est un rectangle noir de la taille de l'image.
Ce que je fais :
1: je charge l'image avec LoadImage pour avoir un Handle de la Bitmap
2: je fais un GetObject pour obtenir la Bitmap
3: je cr=E9e ma structure BITMAPINFO
4: je cr=E9e mon compatibleDC pour l'=E9cran en lui passant NULL comme
param=E8tre
5: je s=E9lectionne mon objet SelectObject
6: je fais ma DIBColorTable
7: je r=E9tablis le Bitmap d'origine avec SelectObject
8: je fais un StretchDIBits ou SetDIBitsToDevice pour afficher et
imprimer
/----------- DEBUT CODE ------------/
_DrawImage(std::string sImageFile, uint uiX, uint uiY, uint uiW /*=3D0*/,
uint uiH /*=3D0*/)
{
HBITMAP hbmpImage, hbmpMemOld;
BITMAP bmp; HDC hdcMem; // about the bitmap (size, color depth...)
PBITMAPINFO info; // Structure for storing the DIB information, it will
be used by 'StretchDIBits()'
int nColors =3D 0; // Used to store the number of colors the DIB has
RGBQUAD rgb[256]; // Used to store the DIB color table
/* Etape 1 */
// The following line loads the bitmap from a file
hbmpImage =3D (HBITMAP) ::LoadImageA(NULL, sImageFile.c_str(),
IMAGE_BITMAP, 0, 0,
LR_CREATEDIBSECTION|LR_LOADMAP3DCOLORS|LR_LOADFROMFILE);
/* Etape 2 */
// Obtain information about 'hbmpImage' and store it in 'bmp'
::GetObject(hbmpImage, sizeof(BITMAP), (LPVOID) &bmp);
nColors =3D (1 << bmp.bmBitsPixel);
if(nColors > 256) nColors =3D 0; // This is when DIB is 24 bit.
// In this case there is not any color table information
/* Etape 3 */
// Now we need to know how much size we have to give for storing "info"
in memory.
// This involves the proper BITMAPINFO size and the color table size.
// Color table is only needed when the DIB has 256 colors or less.
info =3D CreateBitmapInfoStruct(hbmpImage);
// Now for 256 or less color DIB we have to fill the "info" color table
parameter
if(nColors >=3D 0 && nColors <=3D 256)
{
/* Etape 4 */
hdcMem =3D ::CreateCompatibleDC(NULL); // Creating an auxiliary
device context with screen
/* Etape 5*/
hbmpMemOld =3D (HBITMAP) ::SelectObject(hdcMem, hbmpImage); //
Select this bitmap in this DC:
/* Etape 6*/
::GetDIBColorTable(hdcMem, 0, nColors, rgb); // Obtaining the
color table information
// Now we pass this color information to "info"
for(int iCnt =3D 0; iCnt < nColors; ++iCnt)
{
info->bmiColors[iCnt].rgbRed =3D rgb[iCnt].rgbRed;
info->bmiColors[iCnt].rgbGreen =3D
rgb[iCnt].rgbGreen;
info->bmiColors[iCnt].rgbBlue =3D rgb[iCnt].rgbBlue;
}
/* Etape 7*/
// R=E9tablir le bitmap d'origine:
::SelectObject(hdcMem, hbmpMemOld);
}
/* Etape 8 */
// Stretching all the bitmap on a destination rectangle of size
(size_x, size_y)
// and upper left corner at (uiX, uiY)
if( (uiW =3D=3D 0) && (uiH =3D=3D 0) )
// To printer device
// m_hdcCurrent est le HDC de l'imprimante
::SetDIBitsToDevice(m_hdcCurrent,
uiX,
uiY,
info->bmiHeader.biWidth,
info->bmiHeader.biHeight,
0,
0,
0,
info->bmiHeader.biHeight,
bmp.bmBits,
info,
DIB_RGB_COLORS);
else
// To printer device
::StretchDIBits(m_hdcCurrent,
uiX,
uiY,
uiW,
uiH,
0,
0,
bmp.bmWidth,
bmp.bmHeight,
bmp.bmBits,
info,
DIB_RGB_COLORS,
SRCCOPY);
// This mode, DIB_RGB_COLORS indicate the color table are pure RGB
values
// The mode DIB_PAL_COLORS indicate the color table items are index to
the local palette items
//..... Delete les differents objets
}
/----------- FIN CODE ------------/
Je ne vois pas o=F9 le probl=E8me viendrait mais j'ai une piste sur le
fait qu'il faudrait deux HDC (un pour l'=E9cran et un pour
l'imprimante), mais je ne suis pas s=FBr.
Le probl=E8me aussi est que j'ai fait un programme de tests et dans ce
programme simule une impression. Avec cette simulation, j'obtiens la
m=EAme chose que si j'imprime (un rectangle noir).
Mais mon DC sur mon imprimante existe bien c'est "m_hdcCurrent". Il n'est pas null pourtant, je ne comprends pas mais je recherche toujours.
@+ Michel
Et tu le crées où et comment ce DC ?
-- Arnold McDonald (AMcD)
http://arnold.mcdonald.free.fr/
atoub.michel
> Et tu le crées où et comment ce DC ?
En fait, j'ai fais une fonciton NewPage où je le crée ainsi : // internal printer variables HDC m_hdcCurrent; // dans le Header
//---------- dans la fonction NewPage, cette fonction me permet en mode simuler de faire une fenetre // avec un "page" blanche (comme dans Paint) qui représente ma feuille de papier. m_hdcCurrent = ::CreateCompatibleDC(NULL); // create the bitmap that will store the "page" m_hbmpCurrent = ::CreateCompatibleBitmap(m_hdcCurrent, m_uiPageW, m_uiPageH);
et en mode réel dans ma fonction PrintPage je fais : // create a printer DC to spool hdcPrinter = ::CreateDC(NULL, sDeviceName.c_str(), NULL, pdm); // actually print BitBlt(hdcPrinter, 0, -int(uiH), uiW, uiH, m_hdcCurrent, 0, -int(uiH), SRCCOPY);
Voilà, je sais que c'est un peu compliqué mais je suis obligé de suivre cette voie. @+
> Et tu le crées où et comment ce DC ?
En fait, j'ai fais une fonciton NewPage où je le crée ainsi :
// internal printer variables
HDC m_hdcCurrent; // dans le Header
//---------- dans la fonction NewPage, cette fonction me permet en mode
simuler de faire une fenetre
// avec un "page" blanche (comme dans Paint) qui représente ma feuille
de papier.
m_hdcCurrent = ::CreateCompatibleDC(NULL);
// create the bitmap that will store the "page"
m_hbmpCurrent = ::CreateCompatibleBitmap(m_hdcCurrent, m_uiPageW,
m_uiPageH);
et en mode réel dans ma fonction PrintPage je fais :
// create a printer DC to spool
hdcPrinter = ::CreateDC(NULL, sDeviceName.c_str(), NULL, pdm);
// actually print
BitBlt(hdcPrinter, 0, -int(uiH), uiW, uiH, m_hdcCurrent, 0, -int(uiH),
SRCCOPY);
Voilà, je sais que c'est un peu compliqué mais je suis obligé de
suivre cette voie.
@+
En fait, j'ai fais une fonciton NewPage où je le crée ainsi : // internal printer variables HDC m_hdcCurrent; // dans le Header
//---------- dans la fonction NewPage, cette fonction me permet en mode simuler de faire une fenetre // avec un "page" blanche (comme dans Paint) qui représente ma feuille de papier. m_hdcCurrent = ::CreateCompatibleDC(NULL); // create the bitmap that will store the "page" m_hbmpCurrent = ::CreateCompatibleBitmap(m_hdcCurrent, m_uiPageW, m_uiPageH);
et en mode réel dans ma fonction PrintPage je fais : // create a printer DC to spool hdcPrinter = ::CreateDC(NULL, sDeviceName.c_str(), NULL, pdm); // actually print BitBlt(hdcPrinter, 0, -int(uiH), uiW, uiH, m_hdcCurrent, 0, -int(uiH), SRCCOPY);
Voilà, je sais que c'est un peu compliqué mais je suis obligé de suivre cette voie. @+
atoub.michel
Ah oui !! Je voulais dire aussi que si je mets juste avant l'étape 8 dans le code du 1er post : m_hdcCurrent = ::GetDC((HWND) // de la fenetre général);
J'arrive à afficher mon bitmap mais avec le bureau. C'est un premier pas mais avec une partie du bureau de windows sur la page d'impression ça le fait moyen. C'est comme si je faisait un ScreenShot.
Mais, je souhaiterai avoir juste mon bitmap.
@+
Ah oui !! Je voulais dire aussi que si je mets juste avant l'étape 8
dans le code du 1er post :
m_hdcCurrent = ::GetDC((HWND) // de la fenetre général);
J'arrive à afficher mon bitmap mais avec le bureau. C'est un premier
pas mais avec une partie du bureau de windows sur la page d'impression
ça le fait moyen. C'est comme si je faisait un ScreenShot.
Ah oui !! Je voulais dire aussi que si je mets juste avant l'étape 8 dans le code du 1er post : m_hdcCurrent = ::GetDC((HWND) // de la fenetre général);
J'arrive à afficher mon bitmap mais avec le bureau. C'est un premier pas mais avec une partie du bureau de windows sur la page d'impression ça le fait moyen. C'est comme si je faisait un ScreenShot.
Mais, je souhaiterai avoir juste mon bitmap.
@+
Arnold McDonald \(AMcD\)
> m_hdcCurrent = ::CreateCompatibleDC(NULL);
Non. Il te faut créer un DC sur ton imprimante. Par exemple, pour l'imprimante par défaut :
Oki, merci, mais si je souhaite faire un preview. Il faudra mettre quel HDC ? celui de l'écran ou celui de l'imprimante ?
Et est-ce que les fonctions stretchDIBits et SetDIBitsToDevice sont toujours approprié ?
@+
Bertrand Lenoir-Welter
> Oki, merci, mais si je souhaite faire un preview. Il faudra mettre quel HDC ? celui de l'écran ou celui de l'imprimante ?
Si tu veux faire un preview, il te faut un handle sur un DC correspondant à ta zone d'affichage. Si tu veux imprimer, il te faut un autre handle sur un autre DC correspondant à ton imprimante.
Et est-ce que les fonctions stretchDIBits et SetDIBitsToDevice sont toujours approprié ?
Windows a été fait entre autres pour que tu puisse utiliser de la même façon un DC correspondant à l'écran, la mémoire, l'imprimante, etc. Du moment que ton hDC est valide, les fonctions qui en ont besoin sont contentes.
> Oki, merci, mais si je souhaite faire un preview. Il faudra mettre quel
HDC ? celui de l'écran ou celui de l'imprimante ?
Si tu veux faire un preview, il te faut un handle sur un DC
correspondant à ta zone d'affichage. Si tu veux imprimer, il te faut un
autre handle sur un autre DC correspondant à ton imprimante.
Et est-ce que les fonctions stretchDIBits et SetDIBitsToDevice sont
toujours approprié ?
Windows a été fait entre autres pour que tu puisse utiliser de la même
façon un DC correspondant à l'écran, la mémoire, l'imprimante, etc. Du
moment que ton hDC est valide, les fonctions qui en ont besoin sont
contentes.
> Oki, merci, mais si je souhaite faire un preview. Il faudra mettre quel HDC ? celui de l'écran ou celui de l'imprimante ?
Si tu veux faire un preview, il te faut un handle sur un DC correspondant à ta zone d'affichage. Si tu veux imprimer, il te faut un autre handle sur un autre DC correspondant à ton imprimante.
Et est-ce que les fonctions stretchDIBits et SetDIBitsToDevice sont toujours approprié ?
Windows a été fait entre autres pour que tu puisse utiliser de la même façon un DC correspondant à l'écran, la mémoire, l'imprimante, etc. Du moment que ton hDC est valide, les fonctions qui en ont besoin sont contentes.
atoub.michel
Oki, merci à Bertrand Lenoir-Welter, je vais voir cela !!!
@+
Oki, merci à Bertrand Lenoir-Welter, je vais voir cela !!!