Make sure the DLL is an MFC extension DLL and that the App uses MFC as a shared DLL. This way you will be able to allocate/release memory and objects wherever you want.
GKarRacer
Posts
-
CStringArray problem -
how to create 2 splitters in a window (using MFC)They have to CWnd derived classes - most likely derived from CView. In addition they also have to have DECLARE_DYNCREATE in the class header file and IMPLEMENT_DYNCREATE in the class source file. If you look at the default CView classes created for the project you will see these lines. Use "MFC Class" to create the classes instead and derive them from CView. It will then put these lines in automatically for you. The "classCTopRightView" is a special member variable that MFC puts in for runtime class typing and dynamic creation. It uses the name "classCYOURCLASSNAMEHERE" as the member name. The above macros put these in for you.
-
how to create 2 splitters in a window (using MFC)Add another CSplitterWnd variable to your CMainFrame class, e.g. m_RightSplitter. Replace CMainFrame::OnCreateClient with code similar to:
// create splitter window
if (!m_wndSplitter.CreateStatic(this, 1, 2))
{
m_wndSplitter.DestroyWindow();
return FALSE;
}if( ! m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView), CSize(100, 100), pContext) )
return(FALSE);
m_RightSplitter.CreateStatic( &m_wndSplitter, 2, 1, WS_CHILD | WS_VISIBLE, m_wndSplitter.IdFromRowCol(0,1) );
if( ! m_RightSplitter.CreateView(0, 0, RUNTIME_CLASS(CTopRightView), CSize(100, 100), pContext) ||
! m_RightSplitter.CreateView(1, 0, RUNTIME_CLASS(CBottomRightView), CSize(100, 100), pContext) )
{
return(FALSE);
} -
Opening system menu with code don’t workTry this instead:
void TestDlg::OnButton()
{
SendMessage( WM_SYSCHAR, VK_SPACE, 0x20000000 );
} -
Calibration in ATM machinesAnyPopup is an archaic function. I don't see at the moment how SetForegroundWindow, etc. would help you. I need more information about what the calibration process is doing. What is the result from the following code:
pTouch->Recalibrate();
HWND hRecalWnd = FindWindow(...);
DWORD RecalProcID = 0;
DWORD RecalThreadID = GetWindowThreadProcessId( hRecalWnd, &RecalProcID );
char MsgText[1024];
DWORD CurProcID = GetCurrentProcessId();
DWORD CurThreadID = GetCurrentThreadId();sprintf( MsgText, "HWND = %p\nValid = %s\nRecalProcID = %x\nRecalThreadID = %x\nCurProcID = %x\nCurThreadID = %x",
hRecalWnd, IsWindow(hRecalWnd) ? "Yes" : "No",
RecalProcID, RecalThreadID, CurProcID, CurThreadID );
MessageBox( NULL, MsgText, "Test", MB_OK ); -
Playing Sound with Managed C++ .NETTo answer the original question (at least for C++): If all you want to do is play wave files, then you can simply call the PlaySound function. If you need to anything more sophisticated like mixing sound files together, etc. then you'll probably need DirectX. But for basic wave files, the PlaySound function is very easy. From regular C++ (someone else will have to help with proper imports for the managed environment):
#include "mmsystem.h"
#pragma comment( lib, "winnmm.lib" )void SomeFunction()
{
PlaySound( szSoundFileName, NULL, SND_FILENAME | SND_ASYNC | SND_NOWAIT );
} -
Structure Alignment?Generally the default structure alignment (which you should use unless there is a compelling reason not to) is 8 bytes. This aligns all basic data types (up to doubles) to even multiples of their size. Example (using 8 byte alignment):
struct test
{
char a;
int b;
WORD c;
char d;
double e;
};The offset addresses are: a = 0 b = 4 c = 8 d = 10 e = 16 Total size of the structure: 24 bytes Notice there is some wasted space in there. You can add some variables to this and not increase the size of the structure at all. The following structure is still 24 bytes in size, but is now fully packed.
struct test2
{
char a;
char a2;
WORD a3;
int b;
WORD c;
char d;
char d2;
int d3;
double e;
}; -
Icon problemNo, it doesn't. As mentioned above the same IDR_MAINFRAME icon in your resource contains both the large and small icons. To switch between them in the resource editor: Open the icon to edit From the Menu highlight Image/Current Icon Type. An additional menu should open showing you all of the different images for this one icon resource. Click on the selection you wish to edit. If this is a new MFC project using VC++.Net, you may icons for several different sizes and bit widths, e.g. 16x16 16 color, 16x16 256 color, 32x32 16 color, 48x48 true color, etc. You will need to edit each one individually. You may also choose to just delete the extra ones that you don't need. At the very least keep the 16x16 and 32x32 16 color versions.
-
problem while assigning CString(more explanation)I never meant to imply that some conversion wasn't necessary. You're absolutely correct that one of the operands must be a CString. I was merely showing an alternative approach that doesn't require declaring another variable. At the end, both are essentially the same thing.
-
Calibration in ATM machinesI was forgetting that OpenThread is available only for Windows 2000 and up. What operating system is this running on? If this is on 2000 and up, then you can enable those functions by adding: #define WINVER 0x0501 #define _WIN32_WINNT 0x0501 before including the Windows header files. In any case you don't need the OpenThread call and its wait loop just to be able to step through the first few lines in order to determine what threads are created. What does Recalibrate return? TRUE/FALSE or something else?
-
Calibration in ATM machinesIf the Recalibrate function is contained within your own process, then waiting for the process to complete won't work. You'll be waiting for yourself to exit. However, if recalibrate spawns off another thread (sounds possible since it returns immediately) then you can wait on the thread handle instead. Use these tests to verify that another thread was launched. Add code similar to: pTouch->Recalibrate(); HWND hWnd = FindWindow(...); DWORD RecalProcID; DWORD RecalThreadID = GetWindowThreadProcessId( hWnd, &ProcID ); DWORD MyProcID = GetCurrentProcessId(); DWORD MyThreadID = GetCurrentThreadId(); HANDLE hRecalThread = OpenThread( SYNCHRONIZE, FALSE, RecalThreadID ); Put a breakpoint before the recalibrate call. When breakpoint is hit, open the threads window (menu: Debug/Windows/Threads) Monitor this window to see if another thread is created when recalibrate is executed. If in the same process, then RecalProcID will match MyProcID. If different thread, then RecalThreadID will be different than MyThreadID. What you're looking for is that RecalThreadID is created fresh when Recalibrate is called (or when TouchScreen object is created) and that the thread goes away when the calibration is done. If, on the other hand, RecalThreadID is the same as MyThreadID then you cannot use MsgWaitForMultipleObjects to wait on anything as you will be waiting on yourself. Then about the only you can do is check IsWindow periodically inside a PeekMessage loop. Undoubtedly you will need to process messages as the recalibrate itself will be depending on it. What does the Recalibrate function return? Are there any other functions for checking for status? Ultimately if the recalibrate spawns another thread and then the thread goes away when recalibration is complete, then you don't even need the IsWindow loop - just the MsgWaitForMultipleObjects.
-
Converting char* to unicode big-endianConverting to unicode and converting to big-endian are 2 completely separate things. To convert to unicode use mbstowcs from the C runtime library or the Windows API call MultiByteToWideChar. Do you reall need it in big-endian? Are you sending the data over TCP or something? Anyway to convert to big-endian loop over each character in the unicode string buffer and either call htonl from the winsock library or manually swap the bytes yourself like: wchar_t bigendchar = ((littleendwchar & 0xFF) << 8) | ((littleendwchar & 0xFF00) >> 8);
-
Calibration in ATM machinesA couple of things: 1. Does the pTouch->Recalibrate and/or CTouchScreenAPI::Create spawn another process? Or is the recalibrate function contained within your own process (separate thread maybe?) Does recalibrate return immediately? 2. You don't necessarily need to do both the IsWindow loop and the process loop. In any case you need to call GetWindowThreadProcessId before the IsWindow loop. Otherwise, what's the point? The window is gone so the call will always fail. 3. Don't use PROCESS_ALL_ACCESS unless you absolutely have to. Use the minimum security setting to get the job done. Depending on the circumstances and user's security level the call may fail trying for all access. SYNCHRONIZE is all you need for waiting on the handle. If you need to call TerminateProcess then add PROCESS_TERMINATE as well. 4. You might want to use QS_ALLINPUT rather than QS_PAINT so that all messages get processed. See "Waiting in a message_loop"" for an example. 5. Since you're apparently doing all this in a window oriented thread (probably you're main thread), you don't want to use Sleep(1000). This will just freeze up your window while you're waiting in the loop. It'd better doing only the process wait loop, peek message loop, or using a window hook to wait for close notification of the window. 6. It's kind of pointless to call TerminateProcess immediately after SendMessage. You're not exactly giving the process much time to clean up and exit normally. Don't call TerminateProcess except as last resort.
-
Calibration in ATM machinesIsWindow simply returns TRUE or FALSE if the specified window handle is a valid window or not. So, if it suddenly returned FALSE, obviously the window is no longer around. Example:
HWND hWnd = FindWindow(....);
while( true )
{
if( ! IsWindow(hWnd) )
break; // window is gone;
Sleep(1000); // wait a second for window to close
};This is the quick and crude method. Find the window handle and periodically poll to see if the window still exists. You can also do the same thing without polling by using a window hook. Lookup SetWindowsHook and CBTProc for more information. To wait for the process to complete rather than the window. You need to get a process handle that's associated with that window and wait for it to close. This method, of course, will only work if the process doesn't live on after the window is destroyed. Pseudo Example (error checking removed for brevity):
HWND hWnd = FindWindow(...);
DWORD ProcID;
DWORD ThrdID = 0;
HANDLE hProcess;ThrdID = GetWindowThreadProcessId( hWnd, &ProcID );
hProcess = OpenProcess( SYNCRONIZE, FALSE, ProcID );// Wait for the process to complete
WaitForSingleObject( hProcess, INFINITE );
CloseHandle(hProcess); -
TreeView ControlYou can also handle the NM_CLICK notification. Call GetMessagePos to get the mouse coordinates for the message.
-
Calibration in ATM machinesAssuming it's running Windows (is it?), then you can use the standard techniques for any displayed window. For example: Use FindWindow to locate the dialog box. Periodically check if the window still exists (IsWindow). There are other methods to detect the process and when it closes provided that the process doesn't keep running after calibration is complete.
-
Possible? Injection of a CWndEx-Class in MFC-structure?With the code listed, you created two completely separate functions: CEditEx::MyFunc and CInputCtrl::MyFunc. If you have a pointer to a CInputCtrl, it will call CInputCtrl::MyFunc. To use multiple inheritance, what you want is for the code on the 2nd derivation to be more generic and not window oriented. Ths second branch should not be derived from CWnd, CObject, etc. Sort of like this: class CGeneric { virtual bool DoSomething(); } class CMyEdit : public CEdit, CGeneric { bool DoSomething(); }; The CGeneric class won't have direct access to any windowing features. It's similar to using the global functions, but with more inheritance control.
-
Possible? Injection of a CWndEx-Class in MFC-structure?No, this is not directly possible in the C++ language. I've wanted to do this myself on occasion along with making some necessary functions virtual that for some inexplicable reason are not. But there are ways around it to get the job done. Depending on what you'd like to achieve the simplest thing you can do is just to use a global function that takes a CWnd as a parameter. You won't be able to access protected members, but for most cases this generic function should be able to achieve what you want. It's not as pretty certainly, but the most important thing is to get the program to work. Another approach (at least for objects you directly create) would be to multiply inherit. This wouldn't apply to objects that are dynamically created, however.
-
Closing an application.Generally the method I use is to send the ID_APP_EXIT command to the main window. This will then use the same exit procedure as if the user clicked "Exit" from the File menu. For example: AfxGetMainWnd()->SendMessage( WM_COMMAND, ID_APP_EXIT );
-
Enter and EscWhat you need to do is handle the WM_ONGETDLGCODE message for your edit control class. This message tells the dialog box procedure what keys to process for your control and which to skip. For example:
UINT CMyEdit:OnGetDlgCode()
{
return( CEdit::OnGetDlgCode() | DLGC_WANTALLKEYS );
}Then process in OnChar as normal.