|
I have been trying for the last week to print a bitmap in colour unsuccessfully. If anyone can help I would be eternally grateful. The bitmap prints but only in black and white. Below is the code I am using:
BOOL CControlImpresion::ImprimeAImpresora()
{
HDC hdcPrinter;
HDC hdcBmp;
HDC hdc2Bmp;
HBITMAP hOldBitmap;
HBITMAP hOldBitmap2;
HBITMAP hBMP;
HANDLE hPRN;
LONG dpBytesNeeded;
LPDEVMODE lpDevMode;
DOCINFO DocInfo;
SIZE PrinterDimensions;
SIZE BitmapDimensions;
POINT PrinterPosition;
BITMAP Bitmap;
RECT BMPSize;
HDC hDC;
HDC hMemDC;
HGLOBAL hMem;
HBITMAP hNewBitmap;
HBITMAP hBitmap;
BITMAPINFOHEADER BitmapInfoHeader;
LPBITMAPINFOHEADER lpBitmapInfo;
BITMAPINFO BitmapInfo;
LPVOID lpBitBuffer;
/********************************************************************************************/
// ABRIMOS LA IMPRESORA Y OBTENEMOS SU DC
/********************************************************************************************/
// Obtenemos un handle a la impresora:
if (!OpenPrinter((LPTSTR)m_szPrinterName,(LPHANDLE)&hPRN,NULL))
return FALSE;
// Hacer que imprima apaisado y el número de copias establecido
dpBytesNeeded = DocumentProperties(NULL,hPRN,(LPSTR)m_szPrinterName,NULL,NULL,0);
if (!(lpDevMode = (LPDEVMODE)LocalAlloc(LPTR,dpBytesNeeded)))
return FALSE;
if (DocumentProperties(NULL,hPRN,(LPSTR)m_szPrinterName,(PDEVMODE)lpDevMode,NULL,DM_OUT_BUFFER) != IDOK)
return FALSE;
lpDevMode->dmOrientation = DMORIENT_LANDSCAPE;
lpDevMode->dmCopies = m_iNumeroCopias;
lpDevMode->dmFields = DM_ORIENTATION | DM_COPIES;
if (DocumentProperties(NULL,hPRN,(LPSTR)m_szPrinterName,(PDEVMODE)lpDevMode,(PDEVMODE)lpDevMode,DM_IN_BUFFER|DM_OUT_BUFFER) != IDOK)
return FALSE;
// Creamos el DC para la impresora:
if (!(hdcPrinter = CreateDC(m_szPrinterDriver,m_szPrinterName,NULL,(CONST DEVMODE *)lpDevMode)))
return FALSE;
/*********************************************************************************************/
// Obtenemos las dimensiones de la impresora
PrinterDimensions.cx = GetDeviceCaps(hdcPrinter, HORZRES);
PrinterDimensions.cy = GetDeviceCaps(hdcPrinter, VERTRES);
/*********************************************************************************************/
// OBTENEMOS LA CAPTURA DE LA PANTALLA
/********************************************************************************************/
hDC = CreateDC("DISPLAY",0,0,0);
BMPSize.left = BMPSize.top = 0;
BMPSize.right = GetDeviceCaps(hDC, HORZRES);
BMPSize.bottom = GetDeviceCaps(hDC, VERTRES);
hMemDC = CreateCompatibleDC(hDC);
hNewBitmap = CreateCompatibleBitmap(hDC,BMPSize.right,BMPSize.bottom);
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hNewBitmap);
if (!BitBlt(hMemDC,0,0,BMPSize.right,BMPSize.bottom,hDC,jmx_xstartcoord,0,SRCCOPY))
return FALSE;
/********************************************************************************************/
/*********************************************************************************************/
// CREAMOS UN BITMAP COMPATIBLE CON EL DC DE LA IMPRESORA A PARTIR DE LA CAPTURA
/*********************************************************************************************/
BitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfoHeader.biWidth = BMPSize.right;
BitmapInfoHeader.biHeight = BMPSize.bottom;
BitmapInfoHeader.biPlanes = 1;
BitmapInfoHeader.biBitCount = 16;
BitmapInfoHeader.biCompression = BI_RGB;
BitmapInfoHeader.biSizeImage = 0;
BitmapInfoHeader.biXPelsPerMeter = 0;
BitmapInfoHeader.biYPelsPerMeter = 0;
BitmapInfoHeader.biClrUsed = 0;
BitmapInfoHeader.biClrImportant = 0;
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biWidth = BMPSize.right;
BitmapInfo.bmiHeader.biHeight = BMPSize.bottom;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 16;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
BitmapInfo.bmiHeader.biSizeImage = 0;
BitmapInfo.bmiHeader.biXPelsPerMeter = 0;
BitmapInfo.bmiHeader.biYPelsPerMeter = 0;
BitmapInfo.bmiHeader.biClrUsed = 0;
BitmapInfo.bmiHeader.biClrImportant = 0;
// Establecemos la memoria para el bitmap
hMem = GlobalAlloc(GHND,BitmapInfo.bmiHeader.biSize);
// Bloqueamos la memoria y obtenemos un puntero
lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalLock(hMem);
// Guardamos la info del bitmap que hemos preparado
*lpBitmapInfo = BitmapInfo.bmiHeader;
// Calculamos la dimension del bloque de memoria requerido por la imagen
GetDIBits(hMemDC,hNewBitmap,0,(UINT)BitmapInfo.bmiHeader.biHeight,NULL,(LPBITMAPINFO)lpBitmapInfo,DIB_RGB_COLORS);
BitmapInfo.bmiHeader = *lpBitmapInfo;
GlobalUnlock(hMem);
GlobalFree(hMem);
hMem = GlobalAlloc(GHND,BitmapInfo.bmiHeader.biSizeImage);
lpBitBuffer = (LPVOID)GlobalLock(hMem);
// Obtenemos los bits del bitmap
if (GetDIBits(hMemDC,hNewBitmap,0,(UINT)BitmapInfo.bmiHeader.biHeight,lpBitBuffer,(LPBITMAPINFO)&BitmapInfo.bmiHeader,DIB_RGB_COLORS) == 0)
{
// Nos salimos si hay errores
GlobalUnlock(hMem);
DeleteDC(hMemDC);
DeleteDC(hDC);
return FALSE;
}
if ((hBitmap = CreateDIBitmap(hdcPrinter,&BitmapInfoHeader,CBM_INIT,lpBitBuffer,&BitmapInfo,DIB_RGB_COLORS)) == NULL)
{
// Nos salimos si hay errores
GlobalUnlock(hMem);
DeleteDC(hMemDC);
DeleteDC(hDC);
return FALSE;
}
GlobalUnlock(hMem);
/* PBITMAPINFO pBitmapInfo;
PBITMAPINFOHEADER pBitmapInfoHeader;
pBitmapInfo = CreaBitmapInfo(hBitmap);
CreaBMP(".\\bmpFile.bmp",pBitmapInfo,hBitmap,hMemDC);
LPBYTE lpBits;
PBITMAPINFO pbi;
pbi = pBitmapInfo;
pBitmapInfoHeader = (PBITMAPINFOHEADER)pbi;
// Reservamos memoria para los bytes del bitmap
if ((lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED,pBitmapInfoHeader->biSizeImage)) == NULL)
return FALSE;
// Obtenemos el color table (RGBQUAD array) y los bits
if (!GetDIBits(hdcPrinter,hBitmap,0,(WORD)pBitmapInfoHeader->biHeight,lpBits,pbi,DIB_RGB_COLORS))
{
GlobalFree(lpBits);
return FALSE;
}*/
DeleteDC(hMemDC);
DeleteDC(hDC);
// Recuperamos la info del bitmap
if (!GetObject(hBitmap,sizeof(Bitmap),(LPSTR)&Bitmap))
return FALSE;
/*********************************************************************************************/
/*********************************************************************************************/
// AMPLIAMOS LA IMAGEN A LAS DIMENSIONES ADECUADAS A LA IMPRESORA E IMPRIMIMOS
/*********************************************************************************************/
// Calculamos las dimensiones de ampliacion para evitar que la imagen se achate
BitmapDimensions.cy = PrinterDimensions.cy;
BitmapDimensions.cx = Bitmap.bmWidth * (PrinterDimensions.cy / Bitmap.bmHeight);
// Calculamos la posicion de impresion, para que salga la imagen centrada sobre el papel
PrinterPosition.y = 0;
PrinterPosition.x = (PrinterDimensions.cx / 2) - (BitmapDimensions.cx / 2);
// DC origen con la captura
hdcBmp = CreateCompatibleDC(hdcPrinter);
hOldBitmap = (HBITMAP)SelectObject(hdcBmp,hBitmap);
/* PBITMAPINFO pBitmapInfo;
pBitmapInfo = CreaBitmapInfo(hBitmap);
CreaBMP(".\\bmpFile.bmp",pBitmapInfo,hBitmap,hdcPrinter);*/
// DC destino con la imagen ampliada
hdc2Bmp = CreateCompatibleDC(hdcBmp);
hBMP = CreateCompatibleBitmap(hdc2Bmp,BitmapDimensions.cx,BitmapDimensions.cy);
hOldBitmap2 = (HBITMAP)SelectObject(hdc2Bmp,hBMP);
// Ampliamos la captura para ajustarla al tamaño de la impresora
SetMapMode(hdc2Bmp,MM_TEXT);
if (!SetStretchBltMode(hdc2Bmp,HALFTONE))
return FALSE;
if (!SetBrushOrgEx(hdc2Bmp,0,0,NULL))
return FALSE;
if (!StretchBlt(hdc2Bmp,0,0,BitmapDimensions.cx,BitmapDimensions.cy,hdcBmp,0,0,Bitmap.bmWidth,Bitmap.bmHeight,SRCCOPY))
return FALSE;
// Establecemos la info del documento a imprimir
DocInfo.cbSize = sizeof(DOCINFO);
DocInfo.lpszDocName = "Impresión de P.I.: Captura de pantalla";
DocInfo.lpszOutput = NULL;
/* PBITMAPINFO pBitmapInfo;
pBitmapInfo = CreaBitmapInfo(hBitmap);
CreaBMP(".\\bmpFile.bmp",pBitmapInfo,hBitmap,hdcPrinter);*/
// Imprimimos
StartDoc (hdcPrinter, &DocInfo);
StartPage (hdcPrinter);
// El BitBlt funciona
if (!BitBlt(hdcPrinter,PrinterPosition.x,PrinterPosition.y,BitmapDimensions.cx,BitmapDimensions.cy,hdc2Bmp,0,0,SRCCOPY))
return FALSE;
/* PBITMAPINFO pBitmapInfo;
pBitmapInfo = CreaBitmapInfo(hBitmap);
CreaBMP(".\\bmpFile.bmp",pBitmapInfo,hBitmap,hdcPrinter);*/
// Finalizamos la impresion
EndPage (hdcPrinter);
EndDoc (hdcPrinter);
hBitmap = (HBITMAP)SelectObject(hdcBmp,hOldBitmap);
hBMP = (HBITMAP)SelectObject(hdc2Bmp,hOldBitmap2);
// Liberamos los DC
DeleteDC(hdcPrinter);
DeleteDC(hdcBmp);
DeleteDC(hdc2Bmp);
// Liberamos la memoria
LocalFree(lpDevMode);
// Cerramos la impresora
ClosePrinter(hPRN);
return TRUE;
}
|
|
|
|
|
I am relatively new to programming and i need help on coding for state flags. my problem is:
I want to set a state flag which sort of act as a switch for my onpaint() to be executed after my dialog has beem accessed in SDI. How do i code that line in my dialog and Onpaint(). Also, by doing this, will my onpaint() be able to access the updated values in the dialog? (as i need these values in order to draw).will greatly appreciate any kind help.
|
|
|
|
|
If I understand your question, you need a member variable in your CView -derived class. That member variable can then be accessed/changed in any of the methods of the derived class.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
yah something like that, do I add it as member variable to both view and all dialog classes using the "add member variable" in the class view tab and of type:boolean and public? Also , i have another problem: i need the current values of the dialog in order to draw to SDI view, but first i want to capture these values in the SDI doc class, how do i code that assumming the values needed are length, breadth from dialog A. The dialogs are modal.
|
|
|
|
|
In previous versions of the MFC calling COleDateTime::Format with no parameters would return the date formated according to the locale.
In MFC7 this no longer works. It gives the time one hour too early.
I just post this incase anyone is migrating their code to VS.NET to be warned.
Ed
|
|
|
|
|
Does the locale your system thinks you are in operate any kind of daylight saving?
Steve S
|
|
|
|
|
If we're talking about the overload of COleDateTime::Format which takes a DWORD and an LCID (which I think we are), both implementations (MFC 6 and ATL/MFC 7) call the Windows API function VarBstrFromDate , with the same parameters, in the same order. Despite a few class changes to reuse CComBSTR rather than a full-on VARIANT , it's pretty much the same.
However, the implementation of COleDateTime::operator=(const time_t) has changed. The old implementation included a local time conversion (through the localtime function) from a time_t to a struct tm , then through the helper function _AfxOleDateFromTm which performs the computations to produce an Automation-compatible DATE value.
The new implementation stores the supplied time value as a CTime , then uses CTime::GetAsSystemTime to produce a SYSTEMTIME , which is passed to SystemTimeToVariantTime - the OS computes the DATE value, not MFC.
This difference affects the behaviour of COleDateTime::GetCurrentTime in that it now returns an object with the current UTC time, not the local time. If you need the local time, use GetLocalTime , then convert the resulting SYSTEMTIME structure using the appropriate COleDateTime constructor or assignment operator.
|
|
|
|
|
I actually was wrong about the bug being in COleDateTime. Rather it seems to happen in FindFirstFile.
If you compile this code in VC6 the file creation time returned will be the same as shown in windows explorer, however if you compile the exact same code with VS.NET it gives the time one hour less.
HANDLE hSearch;
WIN32_FIND_DATA findFileData;
CString strMask("c:\\*.txt");
CString str;
hSearch = ::FindFirstFile(strMask, &findFileData);
COleDateTime dt;
if (hSearch != INVALID_HANDLE_VALUE)
{
dt = findFileData.ftLastWriteTime;
str = dt.Format();
}
|
|
|
|
|
Sounds like a TZ issue.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
If the same piece of code runing on the same PC gives a different answer depending on if it's compiled with VC6 or VS.NET then it has to be a bug.
I can't see any other explaination
|
|
|
|
|
Not necessarily. Default values have been known to change from version to version. That would not be considered a bug.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
Mike Dimmick has it right. FindFirstFile is working as documented. It returns the last write time in UTC. The behavior you are seeing in VS.NET is documented; the UTC time is NOT converted to local time.
I suspect the change was due to MFC using the ATL class versus it's own. I do know that the new implementation is much smaller than the previous one.
Anyone who thinks he has a better idea of what's good for people than people do is a swine.
- P.J. O'Rourke
|
|
|
|
|
You are right it behaves as documented. However, it previously didn't work this way in VC6 and that's why I put this post here.
because the behavour changes from one version to the other subtle hard to find bugs will be introduced into your application simply by compiling with VS.NET instead of VC6.
|
|
|
|
|
Hi guys,
I was told it's the best to access components of a dialog using DDX control, instead of GetDlgItem. But I think I make some obvious mistakes that have kept me from successfully using the DDX. The problem is like this.
I have two dialogs with their own classes (CMyDlg1 and CMyDlg2). The dialog 2, CMyDlg2 has a Static Text, which I had created a DDX control for it, called m_TextName. What I wanted to do was to open (modal) dialog 2 by clicking on a button in the dialog 1, in the meantime, set the text of the static text in the dialog 2. So what I did, was to have the following in the dialog 1's button clicked function:
void CMyDlg1::OnBnClickedButton1()
{
CMyDlg2 MyDlg2;
MyDlg2.m_TextName.SetWindowText("Testing text");
MyDlg2.DoModal();
}
And it'd cause the app to crash when the button of the dialog 1 is clicked. In the debug, it clearly showed that this line
MyDlg2.m_TextName.SetWindowText("Testing test");
causes the error.
As it looks legal to me in the C++ perspective, could anyone tell me what it could wrong?
Please help.
Thanks alot.
|
|
|
|
|
Simple. You've created the dialog object, but none of the windows controls exist until deep inside DoModal(). The CStatic or whatever it is for m_TextName exists, but the first thing that SetWindowText will do is determine whether 'this' refers to a window. At the point you call it, it doesn't, so it faults.
You can get around this by having a public CString member (or even a method that allows you to set a private/protected member) in CMyDlg2, then your CMyDlg2::OnInitDialog
can call the base CDialog::OnInitDialog (which processes the DDX map), then calls m_TextName.SetWindowText passing the CString.
There, doesn't that make you feel better?
Steve S
|
|
|
|
|
It was a quick reply Steve, thanks alot!
I will try it out now. But just a thought, if it's because the control did not exist before DoModal() is called, wouldn't swapping the DoMadal() and SetWindowText() work?
e.g.
CMyDlg2 MyDlg2;
MyDlg2.DoModal();
MyDlg2.m_TextName.SetWindowText("Testing text");
Interestingly, now the dialog 2 loads after the button click but the text is not set. And the app crashes after close the dialog 2.
Would you mind explaining why it acts like this?
|
|
|
|
|
Ok, to answer my own question,
I think because the DDX controls are processed through CDialog::OnInitDialog(), without calling it first , that CStatic m_TextName was never mapped and known to the window.
And when the dialog 2 is closed, the code proceeds to the SetWindowText line, which therefore crashes the app (m_TextName is not found).
|
|
|
|
|
Not quite.
The CStatic itself exists throughout the lifetime of the CMyDlg2 object. However, the window associated with it only exists during DoModal. The crash happens in both cases (before and after) for the same reason, that you're trying to operate on a non-existent window. The CStatic is really only a wrapper, which can exist with or without a window, but without the window it's pretty much useless.
It's better to use either DDX_Text and public members or else use methods that manipulate non-public members safely, and to put 'one-time-only' per dialog stuff into OnInitDialog, where it belongs.
The hard part is remembering that a CWnd (or derived class) is NOT the same as a window. It has to be attached or otherwise associated (via creation or subclassing) with an OS window.
Steve S
|
|
|
|
|
J.B. wrote:
But just a thought, if it's because the control did not exist before DoModal() is called, wouldn't swapping the DoMadal() and SetWindowText() work?
No, because dialog 1 does not get control again until DoModal() returns.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
hi,
my application is using mysql is database.i connect to mysql using mysql lib files. while connecting from the local host is not an problem. when i try to connect mysql from other machine. i found the following error
Host Auro5(Auro5 my machine name) is not allowed to connect to this MySQL server
any help to me. Thanks in advance.
Murali.M
|
|
|
|
|
there is no problem with your c++ aplication, you need to add the user who is connecting you mysqlserver into the mysql server.
My God is more powerfull Than Your God.
|
|
|
|
|
Look at your priviliges on that machine, not just your localhost login but how you are signed onto the local box.
Best Wishes and Happy Holiday's,
ez_way
|
|
|
|
|
Friends,
My question is related to the Add/Remove Programs dialog that can be opened from control panel of Microsoft Windows Operating Systems.
There are various enteries of curently installed programs there. These enteries are made by the installation program of particular appliation.
But from where this dialog box reads these enteries ??Actually i want to remove certain entry programatically. But i don't know from where to delete it. So that it cannot be shown in this dialog box. I can guess that this dialog reads these enteries from registry but i dunno where are they stored). Can any one tell me ?
|
|
|
|
|
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall Your uninstall program should remove these entries automatically when uninstalling.
|
|
|
|
|
Hi, I really nead a C (not c++) code for deconvolution of signals (not images)usign fft.
Is there anybody that can help me? I'll be very happy.
Thanks, Angeluna.
|
|
|
|
|