|
jkirkerx wrote: I thought that was OK to do
I am not sure that you understand my recommendation. There is nothing wrong with your logic. It will work just fine.
What I am trying to say is that you are essentially copying the data twice. You could have RegQueryValueEx write directly into a buffer passed by the calling function rather than reading it into a local buffer allocated on the stack and then copying it into a buffer allocated on the heap.
It is just a simple matter of being more efficient.
Look on the bright side... at least we are down to complaining about optimizations! A year ago you could barely invoke a MessageBox.
Your doing great and seem to be a very fast learner.
Best Wishes,
-David Delaune
|
|
|
|
|
Well Thanks Randor!
Actually it was October 15, 2011, around 7 months ago that I wrote my first line of c++ code
I changed the registry code to use the LPDWORD like Richard Suggested, See new post above or below.
Do I need to delete [] the pzProjectFolderPath, since I didn't use the new WCHAR[ ] word?. I was thinking, why should I make a new buffer since I already made the buffer in the registry function, and I just need to point to it in the main function.
Based on your thoughts, I want to take one more day and optimized some more, to lessen the chance of an embarrassing moment in the future.
CA_Registry caReg;
WCHAR *pzProjectFolderPath = NULL;
DWORD dwProjectFolderPath = 0;
caReg._read_Registry_ProjectMRUList_Value( L"File1", &dwProjectFolderPath );
if ( dwProjectFolderPath > 0 ) {
pzProjectFolderPath = caReg._read_Registry_ProjectMRUList_Value( L"File1", &dwProjectFolderPath );
_project_Open( pzProjectFolderPath );
}
|
|
|
|
|
DWORD dwProjectPath = 0;
caReg._read_Registry_ProjectMRUList_Value( L"File1", dwProjectPath );
szProject_Path = new WCHAR[ dwProjectPath + 1 ];
This will allocate you a buffer of 1 character. You cannot pass a variable into a function and expect it to have a new value on return. You can only get a value in there by sending its address, something like:
DWORD dwProjectPath = 0;
caReg._read_Registry_ProjectMRUList_Value( L"File1", &dwProjectPath );
szProject_Path = new WCHAR[ dwProjectPath + 1 ];
_read_Registry_ProjectMRUList_Value(PCWSTR pszFilename, PDWORD pdwSize)
{
DWORD size = ...
*pdwSize = size;
}
Binding 100,000 items to a list box can be just silly regardless of what pattern you are following. Jeremy Likness
|
|
|
|
|
Oh,
I didn't know that.
I'm gonna lookup PDWORD for to learn more about it.
I'll be back.
|
|
|
|
|
Microsoft defined types that begin with P or LP are pointers to the type. This article[^] by Ajay Vijayvargiya[^] gives some useful background information about it.
Binding 100,000 items to a list box can be just silly regardless of what pattern you are following. Jeremy Likness
|
|
|
|
|
So I changed my code here just for experimenting and used LPDWORD, might use PDWORD
CA_Registry caReg;
WCHAR *pzProjectFolderPath = NULL;
DWORD dwProjectFolderPath = 0;
caReg._read_Registry_ProjectMRUList_Value( L"File1", &dwProjectFolderPath );
if ( dwProjectFolderPath > 0 ) {
pzProjectFolderPath = caReg._read_Registry_ProjectMRUList_Value( L"File1", &dwProjectFolderPath );
_project_Open( pzProjectFolderPath );
}
Do I need to delete pzProjectFolderPath above?, or is it just a pointer to rgValue in the registry function?
WCHAR* CA_Registry::_read_Registry_ProjectMRUList_Value( WCHAR *pzValue, LPDWORD dwOut )
{
WCHAR *szReturnValue = NULL;
WCHAR *regPath = L"SOFTWARE\\redCopper\\Internet Commerce Engine 5\\ProjectMRUList\\";
HKEY keyHandle;
TCHAR rgValue[ MAX_PATH ];
DWORD dwValue = sizeof(rgValue);
DWORD dwType = REG_SZ;
DWORD regStatus = REG_DWORD;
if(RegOpenKeyEx(HKEY_CURRENT_USER, regPath, 0, KEY_QUERY_VALUE, &keyHandle) == ERROR_SUCCESS) {
regStatus = RegQueryValueEx( keyHandle, pzValue, NULL, &dwType, (LPBYTE)rgValue, &dwValue );
RegCloseKey(keyHandle);
switch ( regStatus ) {
case ERROR_SUCCESS:
{
if (( *dwOut > 0 ) && ( *dwOut < 4096 )) {
szReturnValue = new WCHAR[ *dwOut + 2 ];
for ( DWORD dwI = 0; dwI <= *dwOut; ++dwI ) {
szReturnValue[ dwI ] = rgValue[ dwI ];
}
szReturnValue[ *dwOut ] = L'\0';
DWORD dwErrorCode = GetLastError();
}
else {
*dwOut = wcslen( rgValue );
}
}
break;
case ERROR_FILE_NOT_FOUND:
*dwOut = 0;
break;
case ERROR_MORE_DATA:
*dwOut = 0;
break;
default:
*dwOut = 0;
}
}
else {
*dwOut = 0;
}
return szReturnValue;
}
|
|
|
|
|
jkirkerx wrote: used LPDWORD , might use PDWORD
They evaluate to exactly the same thing, the prefix L is there for historical reasons.
You could improve this by only calling your function once and not bothering about the size parameter, since that is only used within the _read_Registry_ProjectMRUList_Value() function. Just send the key name to the function and let it return a pointer to the value buffer that it allocates with new . The caller can then release that when it's finished with a call to delete[] .
Binding 100,000 items to a list box can be just silly regardless of what pattern you are following. Jeremy Likness
|
|
|
|
|
I'll try that
Thanks Richard
|
|
|
|
|
Hi,
I am somewhat of MFC C++ newbie
I have a uestion regarding virtual/overridable function
In My Case I dealing with the CASyncSocket Class
there are a number of overrideables in this class onSend OnReceive etc....
The examples of these function on the MSDN WebSite
in each these of examples the orignal functions is the last line of code
e.g
CAsyncSocket :: OnSend(nErrorCode);
CAsyncSocket::OnReceive(nErrorCode);
|
|
|
|
|
Usually when you override a virtual function, you still want to execute whatever code is within the base class, that's why you call that method either at the beginning or at the end of your own method. The placement (beginning or end) depends on the specific function, in some instances you want the base code to executed first and sometimes you want it to be executed last.
|
|
|
|
|
In addition to what Albert said, language-wise you are "overriding" a virtual function. In the language, that means you are replacing the functionality provided by the base class with your own implementation. In many examples in courses this is what they show, overriding.
In this instance, and in many such classes in the Microsoft Framework, you are, in reality, "extending" the functionality provided by the base class. So, the base class is giving you the opportunity to do *more stuff* than it would do but it still wants to do it's own stuff too. Hence you need to call the base class explicitly to let it do it's stuff. And, as Albert said, whether you call it first or last depends on the functionality you are extending so the documentation / example should help.
For example, every MFC dialog can have an function that handles the event of "InitDialog", the OnInitDialog() function. Since you want to allow the base CDialog class to do its initialization first, the very first thing you should do in your "OnInitDialog()" is to call CDialog::OnInitDialog().
That is the difference between the language defining "Virtual Functions" and an implementaion of a feature (Asynchronous Sockets) using virtual functions to obtain the desired effect.
|
|
|
|
|
Chuck O'Toole wrote: In this instance, and in many such classes in the Microsoft Framework, you are, in reality, "extending" the functionality provided by the base class.
Well put...
|
|
|
|
|
How to enumerate printers connected to the network in metro apps
|
|
|
|
|
You could start by posting your question in the metro forum.
Binding 100,000 items to a list box can be just silly regardless of what pattern you are following. Jeremy Likness
|
|
|
|
|
|
I assume it is done the same way that any other Windows software does.
Start with EnumPrinters[^] and continue.
Watched code never compiles.
|
|
|
|
|
I copied this off the internet without fully understanding how it works, and now it's not working when I compile as Release version. In Debug it works fine.
Not sure if I should dump it and reinvent the wheel, or if there is just a slight mistake in the code. The part I don't understand is in bold.
WCHAR extension [32];
WCHAR* peek = szFileName + szFileName [ wcslen( szFileName ) - 1 ];
while ( peek >= szFileName )
{
if (*peek == L'.') {
wcsncpy_s ( extension, peek, wcslen( peek ) );
break;
}
peek--;
}
swprintf_s( szFileExtension, L"%s", extension );
Edit:
The peek gets stuck with a 2 dot extension, and won't progress forward like
project.config.user
And then all file extensions are .user after that.
But just in Release
modified 25-Apr-12 22:58pm.
|
|
|
|
|
If you are using MFC, why don't you use CString::ReverseFind('.') ?
|
|
|
|
|
I should of said it was just a stock win32 project in c++
|
|
|
|
|
Further to Flaviu2 said,
if you're not using MFC, this will work:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
wchar_t *wszFilename = L"project.config.user";
wchar_t *extension;
wchar_t *dotPosition;
size_t extensionLength;
dotPosition = wcsrchr(wszFilename, '.');
extensionLength = wcslen(dotPosition);
extension = (wchar_t*) malloc(extensionLength * sizeof(wchar_t));
wcscpy(extension, dotPosition + 1); wprintf(extension);
}
Output:
user
|
|
|
|
|
Ooo, have a 5 'cause it's nice to see people using standard language features and types rather than sucking up to a particular OS/compiler and getting their code stuck on them for evermore.
The only comment I'd make is in the line:
dotPosition = wcsrchr(wszFilename, '.');
Should the character constant be a wide character? I haven't tried compiling it or looking at the standard so I could be very wrong!
Cheers,
Ash
|
|
|
|
|
Thanks mate!
Not so sure, I guess it would have been better to explicitly cast the '.' to a wchar_t. I figured since the function takes a wchar_t that this would be implicitly cast for me.
Compiling with gcc 4.something, the only warning I get was for line 7 (the wszFilename declaration) -
"warning: deprecated conversion from string constant to 'wchar_t*' "
It compiles & runs just fine with the -Wall and -Wextra compiler flags.
If the line in question is changed to:
wchar_t *wszFilename = (wchar_t*)"project.config.user";
Then it compiles with 0 warnings. [EDIT: but crashes like a bus!]
The line should read:
wchar_t *wszFilename = (wchar_t*)L"project.config.user";
Nice catch!
Simon.
modified 26-Apr-12 6:26am.
|
|
|
|
|
If you change wszFilename to a const char * you can avoid the cast. I can't see anywhere wszFilename is modified so you should be alright.
Another thing you might not be aware of: In C you don't need to cast the return value of malloc or calloc - void * is type compatible with any sort of pointer so (at least in C90, not sure about C99) you can convert them to anything implicitly.
Cheers,
Ash
|
|
|
|
|
Well,
I realize that it is just a code sample... but there are alot of novice programmers learning by reading these forums. You might want to free() the memory you allocated for the extension and you forgot to return an integer for the main() function.
Best Wishes,
-David Delaune
|
|
|
|
|
Thanks David,
I certainly had overlooked both of these points. Time I exercised a little more diligence..
Simon
|
|
|
|