|
|
I had in mind switching my videogame from DirectX to GDI. After some attempts at getting a win app working the way I need it and failing I will probably give up on the idea. I should probably keep using DirectX. Thanks for your help Richard and everyone else. Sorry for taking your time, this GDI idea is just a dead end.
modified 10-Aug-22 9:06am.
|
|
|
|
|
I would suggest you remove that link from your message (and future ones), as the system assumes it is spam. And some people here will just flag the message which means it will not get published.
|
|
|
|
|
Hi,
I am following an example from a book and it doesn't work fine.
In a win32 c++ project I am trying to make the following codes to work:
At the window creation the mapped file is created
case WM_CREATE:
{
hMapFile = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL,
PAGE_READWRITE,
0,
1024,
"MyFileMappingObject" );
if ( !hMapFile )
return(-1);
}
break;
There are made modification in mapped file in the following thread function:
DWORD AnotherProcess( LPDWORD lpdwParam )
{
HANDLE hFileMap;
LPTSTR lpMapAddress;
hFileMap = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE,
"MyFileMappingObject" );
lpMapAddress =(LPTSTR)MapViewOfFileEx( hFileMap, FILE_MAP_ALL_ACCESS,
0, 0, 0, lpdwParam );
MessageBox( NULL, lpMapAddress, "Mapped Memmory",
MB_OK | MB_ICONINFORMATION );
strcpy( lpMapAddress, "Received" );
UnmapViewOfFile( lpMapAddress );
return( 0 );
}
There are made modification on mapped file and the thread function is called on the following code:
case IDM_TEST:
{
DWORD dwID;
lpMapAddress = (LPTSTR)MapViewOfFile( hMapFile,
FILE_MAP_ALL_ACCESS,
0, 0, 0 );
strcpy(lpMapAddress, "Data passed from main process.");
FlushViewOfFile( lpMapAddress,
lstrlen( lpMapAddress ) );
hThread = CreateThread( NULL, 0,
(LPTHREAD_START_ROUTINE)AnotherProcess,
lpMapAddress, 0, &dwID);
SetTimer( hWnd, 1, 1000, NULL );
}
break;
If everything is ok all cycle is ended with the timer:
case WM_TIMER:
{
if ( strcmp( lpMapAddress, "Received" ) == 0 )
{
KillTimer( hWnd, 1 );
TerminateThread( hThread, 0 );
MessageBox( hWnd, lpMapAddress, "Done", MB_OK );
UnmapViewOfFile( lpMapAddress );
}
When I put breakpoint in the "AnotherProcess" thread function, after the message box, in the message box no message
is displayed, like lpMapAddress would be empty.
It could be from OpenFileMapping or MapViewOfFileEx to not doing their job? Because in watch table lpMapAddress
has value 0.
After that point, the compiler enters in a kind of assambler code in a inifinite main loop. Maybe here WM_TIMER goes crazy.
Can you help me to figure out what should be done? Where are the things that are nok?
Thank you very much.
|
|
|
|
|
Took me some time to spot the problem (I think):
lpMapAddress =(LPTSTR)MapViewOfFileEx( hFileMap, FILE_MAP_ALL_ACCESS,
0, 0, 0, lpdwParam );
This doesn't make much sense: the last argument of the function is the address where you want it mapped. So you are kind of mapping the memory where it was already mapped. I's suggest to change it to:
lpMapAddress =(LPTSTR)MapViewOfFile( hFileMap, FILE_MAP_ALL_ACCESS,
0, 0, 0);
If you want a shared memory implementation that has been tested, you can find one here. The source file is mlib/src/shmem.cpp
Mircea
|
|
|
|
|
Thank you for the rapid response.
Indeed, now, the code works as I think it should.
I supposed that this was the central idea, to modify the mapped file from two different places, but appears
that something went wrong. I supposed that the LPWORD type of lpdwParam was the problem but I haven't seen a solution.
It appears that it does't like the start address but the all file to be mapped.
Anyway it seems that it's working, and now I can move on in the learning process beacause I want to get the ideea not to
stay to long on each topic.
Thank you very much Mircea for your response and for the links.
Thank you.
|
|
|
|
|
You are very welcome!
Mircea
|
|
|
|
|
Hi,
Please help me understanding the following declaration:
#define EVENBYTE( i ) ((i+7)/8*8)
It represents the definition of function?
If for example I call EVENBYTE( 1 ), the result will be ((1+7)/8*8)?
From where I have extracted de code, the EVENBYTE was called in that way:
int nIconBytes = (EVENBYTE(nWidth)/8)*nHeight;
I don't understand what this kind of declaring is and why to do it in that mode?
Thank you in advance.
|
|
|
|
|
No, it is not a function, it is a macro definition. While, in your case a function defined as:
int evenbyte (int i) {return (i+7)/8*8;} would do the same thing, there is an important difference: a macro definition is expanded at compile time while a function is compiled and later on called at runtime.
When to use one over the other is a question of optimization speed vs memory: a macro definition like your would not incur the overhead of a call but might produce larger code. Meanwhile a function definition would produce smaller code but might take longer to execute.
To solve these type of issues, C++ has introduced inline functions, so in C++ you can write
inline int evenbyte (int i) {return (i+7)/8*8;} and you leave the compiler the choice of expanding it inline (like a macro definition) or make it a function and call it.
One more thing: the macro definition is insensitive to the type of argument. That is both a good thing and a bad thing like in the examples below:
int i1 = 3;
int e1 = EVENBYTE (i1); long i2 = 129;
long e2 = EVENBYTE (e2);
int e3 = EVENBYTE ("abc");
To accomplish the same thing in C++ you would have to use a function template:
template <typename T>
T evenbyte (T i) { return (i+7)/8*8;}
Mircea
|
|
|
|
|
Also worth noting: A macro does not define its own scope, the way a function does. It could refer to other symbols, say,
#define PLUSX(i) (i + x) Which x is added? That depends on where PLUSX is used. In one place it could be a different x than in another place. In a third place, there may be no x defined at all, and you get a compilation error, even if the two first uses of PLUSX went without any error.
A define is a pure textual replacement. If you in your code editor replace 'PLUSX(i)' with '(i + x)' (and change the 'i' in the replacement text to whatever was the name of your actual argument), you are doing by hand the work of the C preprocessor. Or in your case, if in your editor you replace
int nIconBytes = (EVENBYTE(nWidth)/8)*nHeight; with
int nIconBytes = (((nWidth+7)/8*8)/8)*nHeight; then you get the exact same result as with the #define.
Note: I am certainly not suggesting that referring to non-argument variables from macros is a good idea (usually is is not), but understanding how macros differ from functions includes understanding how such references would work.
Personal opinion: #define is among the most mis-used features of the C language. Except for giving symbolic names to simple constants, you should try to avoid it as far as possible.
|
|
|
|
|
In C, #define is sometimes used to do the same thing as templates in C++, which I can understand.
In C++, #define shouldn't be used that way, but C hackers use their preprocessor crapola in C++. It shouldn't even be used to define constants, especially after constexpr showed up.
|
|
|
|
|
coco243 wrote: Please help me understanding the following declaration Kinda looks like something used for calculating Image stride[^].
|
|
|
|
|
Thank you all for your responses.
|
|
|
|
|
Hi,
I have an xlsx file, which i need to read using CDatabase in c++.. Here is the sample application i tried but its throwing an exception while opening the file.
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
CDatabase* pExcelDatabase = NULL;
CString csExcelFile = _T("D:\\ExcelFile.xlsx");
CString csDSN;
if (TRUE == ::PathFileExists(csExcelFile))
{
csDSN.Format(_T("DRIVER=Microsoft Excel Driver (*.xls,*.xlsx);DSN='';DBQ=%s"), (LPCTSTR)csExcelFile);
}
else
{
return NULL;
}
pExcelDatabase = new CDatabase();
HRESULT hr;
try
{
hr = pExcelDatabase->OpenEx(csDSN, CDatabase::noOdbcDialog);
}
catch (...)
{
if (pExcelDatabase)
{
delete pExcelDatabase;
}
return NULL;
}
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
Note: Sometimes, i have to open xls file too, thats the reason in the query i added ".xls" and ".xlsx" file. If i give just ".xls" in the query and input is ".xls" file, the above code is working fine.
Any help is much appreciated.
Thanks
|
|
|
|
|
Sampath579 wrote: its throwing an exception while opening the file.
What exception exactly is throwing?
|
|
|
|
|
Unhandled exception at 0x75B9CA42 in WindowsProject1.exe: Microsoft C++ exception: CDBException at memory location 0x00EFF6CC.
|
|
|
|
|
Unfortunately that gives no clue as to where the exception occurred. So you will need to run the code in the debugger and step through it until you can find where it occurs, and why. Also note you have the following code:
catch (...)
{
if (pExcelDatabase)
{
delete pExcelDatabase;
}
return NULL;
}
So you are catching any exception but ignoring it, which is not a good idea. You need to put some proper code in there to get the type and reason information from the exception.
|
|
|
|
|
Message Closed
modified 1-Aug-22 10:39am.
|
|
|
|
|
Try answering the question you were asked about the exception.
|
|
|
|
|
Sorry for missing this question earlier.. i posted the exception details now.
|
|
|
|
|
Figured it out on my own. Things to be asked or answered.
1) My application is 32 bit.
2) I have MDAC 64 bit on my windows 64bit OS.
3) When the CDatabase OpenEx executes with connection string i mentioned in my above code, it checks in ODBC32.exe in which the required driver (xlsx) is not available.
4) We must have to install the MDAC 32 bit and the required driver to read the xlsx file is will be available.
Hope this answer will be helpful to others in future and thought of writing my analysis.
Regards
Sampath.
Questioning is an Art and Answering will be done by only an Artist.
|
|
|
|
|
What do I need to do to be able to use in C++ UTF8 characters for char * and std::string , or at least for std::string if char * doesn't support it? I'm using std:c++17. I tried the following code to see if it is working without changing anything but it didn't worked and returned ┬┴╩╦≡??Γε? :
#include <iostream>
#include <string>
int main() {
std::string a = "ÂÁÊËðșțâîă";
std::cout << a;
std::cin.get();
}
|
|
|
|
|
Couple of things:
1. UTF8 literal strings are written as this:
std::string a = u8"ÂÁÊËðșțâîă";
2. Support for UTF8 in regular CMD is VERY bad. I haven't tried much in the new Windows terminal.
3. You might find more stuff about UTF8 in my series of articles on CodeProject.
Mircea
|
|
|
|
|
Adding u8 worked, thanks. As for CMD it was used only as a testing display, I don't need it in the actual app, and for testing I ended up writing to a file to see if it is working. And where I actually used it, it did worked.
|
|
|
|
|
You need to set the correct codepage to print the characters from the appropriate set. See chcp | Microsoft Docs[^]. Code page 65001 works for me.
modified 27-Jul-22 10:53am.
|
|
|
|
|