|
I've only seen one article on the Internet that explained how to run a program from memory (rather than from disk). Unfortunately I do not have the URL, nor do I remember what I searched for to find it.
For what reason(s) are you against running the program from disk? While I've never compared the two verbatim, I think that running from disk requires far less code than the other method.
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
Can you help me find it? I'm desperate.
|
|
|
|
|
I would like to convert members in a CStringArray to char[49]. What would be the best way to do this. I tried strncpy (with getting the length of the CStringArray member, but this didnt seem to work).
Thank you.
Rihannsu
|
|
|
|
|
Try this:
char str[49];
strncpy(str, (LPCSTR)array.GetAt(index), 49);
you may replace strncpy with memcpy
ARSALAN MALIK
|
|
|
|
|
When I compile and run this code it starts writing the files to a file but the problem is when it gets to a unicode character probably that has a 0 byte or something it stops processing the file. How can I get this Unicode into a file? What am I doing wrong?
Thanks
#include "stdafx.h"
#include <iostream> //iostream
#include <fstream> //fstream
using namespace std;
#define _WIN32_WINNT 0x0501
#include <windows.h> //windows.h
#define unicode
int main(int argc, char *argv[])
{
WIN32_FIND_DATAW FindFileData;
LPCWSTR lpFileName = (const unsigned short *) L"c:\\exe\\*";
HANDLE hFind;
wofstream outfile("c:\\exe\\new.txt", ios::binary);
hFind = FindFirstFileW(lpFileName, &FindFileData);
outfile << FindFileData.cFileName << endl;
if (hFind == INVALID_HANDLE_VALUE)
{
printf ("Invalid File Handle. GetLastError reports %d\n",
GetLastError ());
return (0);
}
else
{
while (FindNextFileW(hFind, &FindFileData) != 0)
{
outfile << FindFileData.cFileName << endl;
}
outfile.close();
FindClose(hFind);
return (1);
}
}
|
|
|
|
|
Is there a way to save the printer & print options that a user selects from the CPrintDialog::DoModal() function into an ini file/registry entry? I want the user to be able to set up certain options when printing checks so that they won't have to change printers/trays each time they want to print a check.
Thanks,
Chad
|
|
|
|
|
Save the DEVMODE structure, device name, driver name, and port name from the m_pd member. You can then pass them to the CDC::CreateDC() function to create the printer DC that you use for printing.
"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 I have the following code to save the printer options:
CPrintDialog pd(TRUE);<br />
pd.DoModal();<br />
DEVMODE *dm=pd.GetDevMode();<br />
theApp.WriteProfileBinary("CheckPrinter", "DevMode", (LPBYTE)&dm, sizeof(dm));<br />
theApp.WriteProfileString("CheckPrinter", "DeviceName", (LPCTSTR) pd.GetDeviceName());<br />
theApp.WriteProfileString("CheckPrinter", "PortName", (LPCTSTR) pd.GetPortName());<br />
theApp.WriteProfileString("CheckPrinter", "DriverName", (LPCTSTR) pd.GetDriverName());
Then to read it back:
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 />
CDC* pDC=new CDC();<br />
pDC->CreateDC(csDriverName, csDeviceName, csPortName, hDevMode);
Does this look right? I am not familar with the Get/WriteProfileBinary functions and it didn't look like it was retreiving the information correctly when I debugged it.
Also how would I get the same options back into a CPrintDialog object so that a user could change the options?
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.
Thanks,
Chad
|
|
|
|
|
crowbarcberg wrote:
DEVMODE *dm=pd.GetDevMode();
theApp.WriteProfileBinary("CheckPrinter", "DevMode", (LPBYTE)&dm, sizeof(dm));
dm is a pointer to a DEVMODE structure, so sizeof(dm) returns the size of the pointer - 4 bytes. Use sizeof(DEVMODE) and it should work correctly.
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
That didn't seem to work either, when I try to retreive the DEVMODE structure via:
<br />
DEVMODE *hDevMode;<br />
UINT nl;<br />
theApp.GetProfileBinary("CheckPrinter", "DevMode", (LPBYTE*)&hDevMode, &nl);
the string values have garbage in them, and most of the other paramaters are 0, or rather large values. Any other ideas?
Thanks,
Chad
|
|
|
|
|
What is the return value of GetProfileBinary? what is the value in nl?
"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
|
|
|
|
|
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
|
|
|
|
|