|
crowbarcberg wrote:
DEVMODE *dm=pd.GetDevMode();
theApp.WriteProfileBinary("CheckPrinter", "DevMode", (LPBYTE)&dm, sizeof(dm));
dm is a pointer, so what you are saving here is the address of the DEVMODE structure, not the data in the DEVMODE structure.
theApp.WriteProfileBinary("CheckPrinter", "DevMode", (LPBYTE)dm, sizeof(DEVMODE));
crowbarcberg wrote:
Also how would I get the same options back into a CPrintDialog object so that a user could change the options?
That is the fun part. You have to rebuild the hDevMode and hDevNames members of the m_pd member of the CPrintDialog dialog. Remember that those are HGLOBAL handles to movable global memory objects, not pointers to a locally allocated memory block. Here is code that I use to do this:
LPDEVMODE pDM = pConfig->StringToDevMode(pConfig->DevMode);
int size = sizeof(DEVMODE);
HGLOBAL hDEVMODE = GlobalAlloc(GHND, size);
void *pV = GlobalLock(hDEVMODE);
memcpy(pV, pDM, size);
GlobalUnlock(pV);
delete pDM;
pDM = NULL;
size = sizeof(DEVNAMES);
size += (pConfig->Printer.GetLength() + 1) * sizeof(TCHAR);
size += (pConfig->Port.GetLength() + 1) * sizeof(TCHAR);
size += (pConfig->Driver.GetLength() + 1) * sizeof(TCHAR);
HGLOBAL hDEVNAMES = GlobalAlloc(GHND, size);
LPDEVNAMES pDN = (LPDEVNAMES)GlobalLock(hDEVNAMES);
pDN->wDefault = 0;
pDN->wDriverOffset = sizeof(DEVNAMES);
pDN->wDeviceOffset = (WORD)(pDN->wDriverOffset + pConfig->Driver.GetLength() + 1);
pDN->wOutputOffset = (WORD)(pDN->wDeviceOffset + pConfig->Printer.GetLength() + 1);
_tcsncpy((TCHAR *)((int)pDN + pDN->wDriverOffset), pConfig->Driver, pConfig->Driver.GetLength());
_tcsncpy((TCHAR *)((int)pDN + pDN->wDeviceOffset), pConfig->Printer, pConfig->Printer.GetLength());
_tcsncpy((TCHAR *)((int)pDN + pDN->wOutputOffset), pConfig->Port, pConfig->Port.GetLength());
GlobalUnlock(pDN);
CPrintSetupDialog dlg(this);
dlg.m_pd.hDevMode = hDEVMODE;
dlg.m_pd.hDevNames = hDEVNAMES;
if (dlg.DoModal() == IDOK)
{
pConfig->Printer = dlg.GetDeviceName();
pConfig->Driver = dlg.GetDriverName();
pConfig->Port = dlg.GetPortName();
m_EditSendTo.SetWindowText(pConfig->Printer);
pDM = dlg.GetDevMode();
pConfig->DevMode = pConfig->DevModeToString(pDM);
GlobalUnlock(pDM);
}
else
{
GlobalFree (hDEVMODE);
}
GlobalFree (hDEVNAMES);
crowbarcberg wrote:
And finally where should I call the CDC::CreateDC() function from the view class so that the CPrintDialog dialog won't be displayed again? Currently I have OnPreparePrinting(), OnBeginPrinting(), OnEndPrinting(), and OnPrint() functions extended in my view class.
The Print dialog is called from OnPreparePrinting(), so I think I would do it there. Have a look in MSDN[^] for more information. I have done this only in a dialog based app so I did not have the Doc-View framework at my disposal and have not had to worry about which function to override.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it! Honoured as one of The Most Helpful Members of 2004
|
|
|
|
|
You were right I was just saving the address of the DEVMODE structure, no wonder it was reading back in garbage.
In the second part what are the pConfig and m_EditSendTo variables? And is the CPrintSetupDialog just a class you extended from CPrintDialog?
I will take a look at the MSDN docs and let you know what works for calling CreateDC().
Thanks!
Chad
|
|
|
|
|
pConfig is a pointer to a class that stores all my configuration data, the printer stuff is just a small part it. m_EditSendTo is an edit control that displays the selected printer and CPrintSetupDialog is a subclass of CPrintDialog.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it! Honoured as one of The Most Helpful Members of 2004
|
|
|
|
|
Ok so here is the function that I have that is suppose to read values from the registry and setup the CPrintDialog with those values:
<br />
void CMainFrame::OnFileCheckPrintSetup() <br />
{<br />
DEVMODE *hDevMode;<br />
UINT nl;<br />
CString csDeviceName, csPortName, csDriverName;<br />
theApp.GetProfileBinary("CheckPrinter", "DevMode", (LPBYTE*)&hDevMode, &nl);<br />
theApp.GetProfileString("CheckPrinter", "DeviceName", csDeviceName);<br />
theApp.GetProfileString("CheckPrinter", "PortName", csPortName);<br />
theApp.GetProfileString("CheckPrinter", "DriverName", csDriverName);<br />
<br />
CPrintDialog dlg(TRUE);<br />
LPDEVMODE pDM;<br />
HGLOBAL hDEVNAMES;<br />
HGLOBAL hDEVMODE;<br />
BOOL bLoadedData=FALSE;<br />
<br />
if(!csDeviceName.IsEmpty()&&!csPortName.IsEmpty()&&!csDriverName.IsEmpty())<br />
{<br />
bLoadedData=TRUE;<br />
<br />
pDM = hDevMode;<br />
int size = sizeof(DEVMODE);<br />
hDEVMODE = GlobalAlloc(GHND, size);<br />
void *pV = GlobalLock(hDEVMODE);<br />
memcpy(pV, pDM, size);<br />
GlobalUnlock(pV);<br />
delete pDM;<br />
pDM = NULL;<br />
<br />
size = sizeof(DEVNAMES);<br />
size += (csDeviceName.GetLength() + 1) * sizeof(TCHAR);<br />
size += (csPortName.GetLength() + 1) * sizeof(TCHAR);<br />
size += (csDriverName.GetLength() + 1) * sizeof(TCHAR);<br />
<br />
hDEVNAMES = GlobalAlloc(GHND, size);<br />
LPDEVNAMES pDN = (LPDEVNAMES)GlobalLock(hDEVNAMES);<br />
pDN->wDefault = 0;<br />
pDN->wDriverOffset = sizeof(DEVNAMES);<br />
pDN->wDeviceOffset = (WORD)(pDN->wDriverOffset + csDriverName.GetLength() + 1);<br />
pDN->wOutputOffset = (WORD)(pDN->wDeviceOffset + csDeviceName.GetLength() + 1);<br />
_tcsncpy((TCHAR *)((int)pDN + pDN->wDriverOffset), csDriverName, csDriverName.GetLength());<br />
_tcsncpy((TCHAR *)((int)pDN + pDN->wDeviceOffset), csDeviceName, csDeviceName.GetLength());<br />
_tcsncpy((TCHAR *)((int)pDN + pDN->wOutputOffset), csPortName, csPortName.GetLength());<br />
GlobalUnlock(pDN);<br />
<br />
dlg.m_pd.hDevMode = hDEVMODE;<br />
dlg.m_pd.hDevNames = hDEVNAMES;<br />
}<br />
<br />
<br />
<br />
if(dlg.DoModal()==IDOK)<br />
{<br />
DEVMODE *dm=dlg.GetDevMode();<br />
theApp.WriteProfileBinary("CheckPrinter", "DevMode", (LPBYTE)dm, sizeof(DEVMODE));<br />
theApp.WriteProfileString("CheckPrinter", "DeviceName", (LPCTSTR) dlg.GetDeviceName());<br />
theApp.WriteProfileString("CheckPrinter", "PortName", (LPCTSTR) dlg.GetPortName());<br />
theApp.WriteProfileString("CheckPrinter", "DriverName", (LPCTSTR) dlg.GetDriverName());<br />
<br />
if(bLoadedData)<br />
GlobalUnlock(pDM);<br />
}<br />
else<br />
{<br />
if(bLoadedData)<br />
GlobalFree(hDEVMODE);<br />
}<br />
<br />
if(bLoadedData)<br />
GlobalFree(hDEVNAMES);<br />
}<br />
It reads/saves them fine, the problem is that it isn't correctly setting up the CPrintDialog with the read in options. Am I missing something?
Thanks,
Chad
|
|
|
|
|
Have a look at CWinApp::SelectPrinter , it may be better suited for you if you are using only one printer for all your documents (or have only one SDI document).
I have multiple documents that can be printed to different printers at different times with different formats, all without any user input, so I could not use CWinApp 's built in printer support.
There is one thing I did miss telling you is the DEVMODE extra data (dmDriverExtra member). If you do not correctly save that data you may be loosing some information.
Otherwise the code you posted looks fine. You will just have to step through your code in the debugger to see if there is anything going amiss.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it! Honoured as one of The Most Helpful Members of 2004
|
|
|
|
|
Actually the problem was reading in the strings with the GetProfileString() call I had:
theApp.GetProfileString("CheckPrinter", "DeviceName", csDeviceName);
which should have been:
csDeviceName=theApp.GetProfileString("CheckPrinter", "DeviceName", "");
so that was an easy fix.
Now the function is working fine, except when the program is closed. After I reopen the program I get an unhandled exception in COMDLG32.DLL (0xC0000005) Access Violation after the dlg.DoModal() call. When debugging the exception comes after executing: m_pd.hwndOwner = PreModal(); . Here is the code from the MFC file DLGPRNT.CPP:
<br />
int CPrintDialog::DoModal()<br />
{<br />
ASSERT_VALID(this);<br />
ASSERT(m_pd.Flags & PD_ENABLEPRINTHOOK);<br />
ASSERT(m_pd.Flags & PD_ENABLESETUPHOOK);<br />
ASSERT(m_pd.lpfnPrintHook != NULL);
ASSERT(m_pd.lpfnSetupHook != NULL);
<br />
m_pd.hwndOwner = PreModal();<br />
int nResult = ::PrintDlg(&m_pd);<br />
PostModal();<br />
return nResult ? nResult : IDCANCEL;<br />
}
I did check the dmDriverExtra member and it was saved correctly.
I also tried using the SelectPrinter function by just replacing:
dlg.m_pd.hDevMode = hDEVMODE;<br />
dlg.m_pd.hDevNames = hDEVNAMES;
with:
theApp.SelectPrinter(hDEVNAMES, hDEVMODE, FALSE);
while it didn't throw an error, it didn't populate the CPrintDialog with the correct printer/values. This application has a MDI, and what I am doing is an attempt to setup a different printer for checks, cash receipts, and reports with out user interaction (once they have been setup of course).
Thanks again,
Chad
|
|
|
|
|
OK so the problem was saving the dmDriverExtra param, which contains the number of bytes of private driver-data that follow the structure. So adding dm->dmDriverExtra=0; before saving the DEVMODE structure fixed it. Here is the completed function, included for completeness:
<br />
BOOL CMainFrame::SetupPrinter(CString csPrinter, CPrintDialog* pDlg)<br />
{<br />
DEVMODE *hDevMode=NULL;<br />
UINT nl;<br />
CString csDeviceName, csPortName, csDriverName;<br />
theApp.GetProfileBinary(csPrinter, "DevMode", (LPBYTE*)&hDevMode, &nl);<br />
csDeviceName=theApp.GetProfileString(csPrinter, "DeviceName", "");<br />
csPortName=theApp.GetProfileString(csPrinter, "PortName", "");<br />
csDriverName=theApp.GetProfileString(csPrinter, "DriverName", "");<br />
<br />
BOOL bLoadedDialog=TRUE;<br />
if(pDlg==NULL)<br />
{<br />
pDlg=new CPrintDialog(TRUE);<br />
bLoadedDialog=FALSE;<br />
}<br />
<br />
LPDEVMODE pDM;<br />
HGLOBAL hDEVNAMES;<br />
HGLOBAL hDEVMODE;<br />
BOOL bLoadedData=FALSE;<br />
BOOL bCancel=FALSE;<br />
<br />
if(!csDeviceName.IsEmpty()||!csPortName.IsEmpty()||!csDriverName.IsEmpty()||hDevMode!=NULL)<br />
{<br />
bLoadedData=TRUE;<br />
<br />
pDM = hDevMode;<br />
int size = sizeof(DEVMODE);<br />
hDEVMODE = GlobalAlloc(GHND, size);<br />
void *pV = GlobalLock(hDEVMODE);<br />
memcpy(pV, pDM, size);<br />
GlobalUnlock(pV);<br />
delete pDM;<br />
pDM = NULL;<br />
<br />
size = sizeof(DEVNAMES);<br />
size += (csDeviceName.GetLength() + 1) * sizeof(TCHAR);<br />
size += (csPortName.GetLength() + 1) * sizeof(TCHAR);<br />
size += (csDriverName.GetLength() + 1) * sizeof(TCHAR);<br />
<br />
hDEVNAMES = GlobalAlloc(GHND, size);<br />
LPDEVNAMES pDN = (LPDEVNAMES)GlobalLock(hDEVNAMES);<br />
pDN->wDefault = 0;<br />
pDN->wDriverOffset = sizeof(DEVNAMES);<br />
pDN->wDeviceOffset = (WORD)(pDN->wDriverOffset + csDriverName.GetLength() + 1);<br />
pDN->wOutputOffset = (WORD)(pDN->wDeviceOffset + csDeviceName.GetLength() + 1);<br />
_tcsncpy((TCHAR *)((int)pDN + pDN->wDriverOffset), csDriverName, csDriverName.GetLength());<br />
_tcsncpy((TCHAR *)((int)pDN + pDN->wDeviceOffset), csDeviceName, csDeviceName.GetLength());<br />
_tcsncpy((TCHAR *)((int)pDN + pDN->wOutputOffset), csPortName, csPortName.GetLength());<br />
GlobalUnlock(pDN);<br />
<br />
pDlg->m_pd.hDevMode = hDEVMODE;<br />
pDlg->m_pd.hDevNames = hDEVNAMES;<br />
}<br />
<br />
if(pDlg->DoModal()==IDOK)<br />
{<br />
DEVMODE *dm=pDlg->GetDevMode();<br />
dm->dmDriverExtra=0;
theApp.WriteProfileBinary(csPrinter, "DevMode", (LPBYTE)dm, sizeof(DEVMODE));<br />
theApp.WriteProfileString(csPrinter, "DeviceName", (LPCTSTR) pDlg->GetDeviceName());<br />
theApp.WriteProfileString(csPrinter, "PortName", (LPCTSTR) pDlg->GetPortName());<br />
theApp.WriteProfileString(csPrinter, "DriverName", (LPCTSTR) pDlg->GetDriverName());<br />
<br />
if(bLoadedData)<br />
GlobalUnlock(pDM);<br />
}<br />
else<br />
{<br />
bCancel=TRUE;<br />
if(bLoadedData)<br />
GlobalFree(hDEVMODE);<br />
}<br />
<br />
if(bLoadedData)<br />
GlobalFree(hDEVNAMES);<br />
<br />
if(!bLoadedDialog)<br />
delete pDlg;<br />
<br />
if(bCancel)<br />
return FALSE;<br />
else<br />
return TRUE;<br />
}<br />
|
|
|
|
|
Ok so now it's time to figure out how to use the data that I saved...
In the view's OnPreparePrinting() function how can I override the function so that it won't display the CPrintDialog unless the paramaters that I saved previously are missing? The problem is the CPrintInfo's m_pPD->m_pd.hDC var can't be NULL after the function is called.
Secondly to switch between printers can I just have a call like:
pDC->CreateDC(m_csCashDriverName, m_csCashDeviceName, m_csCashPortName, m_hCashDevMode);
in the OnDraw() function of my view class when I want to send the output to a different printer?
Thanks, Chad
|
|
|
|
|
In OnPreparePrinting, do not call DoPreparePrinting if you do not want the print dialog.
Read MSDN[^] to get a complete over view of printing in MFC.
This page is linked from the page I gave you earlier, be sure to read the entire section on printing, follow the links given.
Maybe also read the printing articles here on CP[^].
Just a suggestion, but sometimes the MFC framework does not fit the model you want to use, so rather than fight MFC, it may be better to roll your own printing model that better fits what you are trying to do.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it! Honoured as one of The Most Helpful Members of 2004
|
|
|
|
|
Quick question: How do I find out what Version #, Service Pack(s), and other versioning info for my Visual Studio 6.0?
When I click Help --> About Visual C++, I don't get anything useful.
Thanks.
Johnny
|
|
|
|
|
MS info about service packs is dreadful. Do you have VB installed? If so, it tells you on its splash screen which SP it has. In which case the chances are that VC++ will be at the same level.
However, a few years ago I remember there being a web page somewhere which listed various DLLs and their versions against the SP versions.
Kevin
|
|
|
|
|
Thanks. I looked in a few places (Add/Remove Programs, through Visual InterDev 6.0) nothing very useful. InterDev reported (SP5), but I didn't think I was that current so it makes me suspicious of this number tied into Visual Studio (VC++ 6.0).
Anyways, if I need to get current (establish a baseline for me and my fellow developers), I can get the latest Service Pack http://msdn.microsoft.com/vstudio/downloads/updates/sp/vs6/sp5/faq.aspx[^]
as it sez that SPs are cumulative and that the latest encompasses the fixes from the previous SPs.
Thanks!
Johnny
|
|
|
|
|
Well, I guess if all the constituent apps. were installed at the same time then V InterDev being at SP5 probably means they all are. However, if any indvidual apps. were reinstalled then you'd have to reapply the SP. BTW, are you aware that the latest SP is SP6? It was released about a year ago.
Kevin
|
|
|
|
|
See here:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\6.0\ServicePacks
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
Hi everyone!
I'm trying to develop an application that uses a control just like the one used on Windows XP to test the hardware of microphone. Looks like a progressBar, that every time that you speaks on the microphone, it goes up and down showing something like the frequence of the wave.
Does anybody knows how can I implement this kind of control?
thanks,
cheers!
|
|
|
|
|
|
That's it!
thanks Ravi!
cheers!
|
|
|
|
|
Who can teach me how to show different view in the CSplitterWnd ?
I want to show different view in the second pane if I click the button in the
first pane.
|
|
|
|
|
There are several examples available here at CP and on the Web. Here's what I've implemented.
I have a CSplitterWndEx object that belongs to the frame class. In the left pane's handler (where the different view type is selected) I get a pointer to the frame's CSplitterWndEx object, and then call that object's ReplaceView() method. The ReplaceView() method looks like:
if ((GetPane(nRow, nCol)->IsKindOf(pViewClass)) == TRUE)
return;
CListView pActiveView = (CListView *) GetParentFrame()->GetActiveView();
if (NULL == pActiveView || GetPane(nRow, nCol) == pActiveView)
bSetActive = TRUE;
CDocument *pDoc = ((CListView *) GetPane(nRow, nCol))->GetDocument();
pDoc->m_bAutoDelete = FALSE;
((CListView *) GetPane(nRow, nCol))->DestroyWindow();
pDoc->m_bAutoDelete = TRUE;
CCreateContext context;
context.m_pNewViewClass = pViewClass;
context.m_pCurrentDoc = pDoc;
context.m_pNewDocTemplate = NULL;
context.m_pLastView = NULL;
context.m_pCurrentFrame = NULL;
CreateView(nRow, nCol, pViewClass, size, &context);
pNewView = (CListView *) GetPane(nRow, nCol);
if (TRUE == bSetActive)
GetParentFrame()->SetActiveView(pNewView);
RecalcLayout();
pDoc->UpdateAllViews(NULL); I would call this method with something like:
pMainFrame->GetSplitterWnd()->ReplaceView(0, 1, RUNTIME_CLASS(CMeetView), CSize(0, 0));
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
HI ,
I hav to mak a project on packet capturing. I recently discovered a library called WinPCap. This works efficiently for networks. But i cannot include the library and work with it. It doesnot except the commands used in WinPCap. Anyone who hav used it in his software will be of great help to me. Guide me how to use WinPCap in my project with VC++ MFC.
THANK YOU
I require ur help
|
|
|
|
|
why dont u use windows raw sockets for packet capturing.
Tutorial Here
|
|
|
|
|
do u know the differences between command.com and cmd.exe?
i guess they do exactly same things.
thx
includeh10
|
|
|
|
|
command.com is used for backward compatibility with 16-bit and Windows 9x applications. cmd.exe is not available on either.
One obvious difference is how each handles the space character. For example, the command md this folder has spaces would fail with command.com but would work with cmd.exe, although four folders would get created. To remedy this, the folder name must be surrounded by quotation marks (md "this folder has spaces").
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
1. DavidCrow wrote:
cmd.exe is not available on either
what does it mean? please explain.
2. is "MS-DOS prompt" command.com or cmd.exe or else?
3. do all windows OS from win95 to NT, XP etc contain both of them?
i know almost NULL about DOS, currently I have to use it.
includeh10
|
|
|
|
|
includeh10 wrote:
what does it mean? please explain.
It means that cmd.exe is not part of MS-DOS or Windows 9x.
includeh10 wrote:
2. is "MS-DOS prompt" command.com or cmd.exe or else?
Based on my earlier reply, it's obvious that MS-DOS uses command.com.
includeh10 wrote:
3. do all windows OS from win95 to NT, XP etc contain both of them?
No. cmd.exe is not part of Windows 9x.
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|