|
I've always found this to be a disaster. I got around it by rolling my own dialog which has a preview, controls for choosing page layout and a button that brings up the traditional printer to choose if you want to change printers. I bring it up in OnPrint.
Christian
#include "std_disclaimer.h"
People who love sausage and respect the law should never watch either one being made.
The things that come to those who wait are usually the things left by those who got there first.
|
|
|
|
|
Hi there,
Please help me, I have been so frustrated. I am working on a Win32 DLL. Inside the dll, I am trying to create a popup window which is hidden and covers the entire desktop so I can process mouse message across the screen and do rubber banding. I am doing this because of the restriction of SetCapture(HWND hwnd) API.
What I can do now is that as soon as the client loads the DLL, a hidden window will be created and mouse messages will be processed in GrabProc Callback function. Instead of creating the hidden window when the dll is first loaded, I am hoping to create a hidden window when the mouse is down and destroy it when the mouse it up.
I am a newbie on Windows Programming. Would someone please give me some pointers and show me how to accomplish what I need. Thank you very much for your help.
BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
CreateHiddenWindow();
}
}
BOOL CreateHiddenWindow()
{
static TCHAR szAppName[] = TEXT ("Test") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = GrabProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = g_hInstance ;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindowEx(WS_EX_TRANSPARENT,
szAppName, NULL,
WS_POPUP, 0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL, NULL, g_hInstance, NULL);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK GrabProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
// Handle mouse down, move, up messages for entire screen
// rubber banding
switch (message)
{
case WM_LBUTTONDOWN:
// Create hidden window
break;
case WM_MOUSEMOVE:
break;
case WM_LBUTTONUP:
// Destroy hidden window
break;
}
};)
|
|
|
|
|
Is it possible to specify a non Windows' control when deriving a class from CCtrlView? Ideally I would like to specify the class name of my CWnd derived class. I have tried, but it always fails.
Cheers,
James Millson
|
|
|
|
|
What do you mean by "it fails"? It doesn't compile? It crashes?
--Mike--
http://home.inreach.com/mdunn/
We've secretly replaced the msdn.microsoft.com servers with Atari 800XLs. Let's see if anyone notices....
|
|
|
|
|
I get the "Cannot create blank document" message.
Cheers,
James Millson
|
|
|
|
|
subj.
I try:
void CTest::OnPaint()
{
CPaintDC dc(this);
CMemDC memdc(&dc);
CRect clip;
memdc.GetClipBox(&clip);
memdc.FillSolidRect(clip, GetSysColor (COLOR_3DLIGHT));
DefWindowProc(WM_PAINT, (WPARAM)memdc->m_hDC, (LPARAM)0);
}
BOOL CTestDlg::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
but anyway my *picture control* flickering and after max/min window's size flicks too. Even more when I open any file by CFileDialog my controls aren't repainted.
What's wrong?
|
|
|
|
|
For a start, handle WM_ERASEBKGND, not WM_PAINT.
--Mike--
http://home.inreach.com/mdunn/
We've secretly replaced the msdn.microsoft.com servers with Atari 800XLs. Let's see if anyone notices....
|
|
|
|
|
Move all WM_PAINT code to WM_ERASEBKGND? or what?
|
|
|
|
|
Yes. Since you are painting a custom background color, do it in WM_ERASEBKGND.
--Mike--
http://home.inreach.com/mdunn/
We've secretly replaced the msdn.microsoft.com servers with Atari 800XLs. Let's see if anyone notices....
|
|
|
|
|
>We've secretly replaced the msdn.microsoft.com servers with Atari 800XLs. Let's see >if anyone notices....
I thought MSDN online seemed a bit quicker than normal!
|
|
|
|
|
Micahel is absolutely right, but I'll also point out that when you call CPaintDC the screen is blanked, so if you ever have to draw anything in OnPaint and have trouble with flicker, don't create your PaintDC until you're about to copy the memDC over the top of it. Otherwise you may stop tearing, but you won't do a thing about flicker.
Christian
#include "std_disclaimer.h"
People who love sausage and respect the law should never watch either one being made.
The things that come to those who wait are usually the things left by those who got there first.
|
|
|
|
|
I don't understand this piece of code...
Where do you get CMemDC from? I don't have it?
Also, why are you not calling BitBlt to eliminate flickering?
Thx,
/Tommy
|
|
|
|
|
Hello,
Im having some troubles with CString commands.. I have a text file that I am opening with CFile and reading into a CString called strSource... There is a line in the text file like this for example (This is a line in line of text in my "text file" test test) ..
Im trying to search the CString strSource and find "my" then pull the information out of the "" just to the right of "my".. so that I end up with a string with a value of "text file".. in this text file "my" is a unique line of text..
Thanks in advance for you help!
Rob
Rob Jones
|
|
|
|
|
Nothing terribly difficult about it
int nMyIndex, nFirstQuoteIndex, nSecondQuoteIndex;
nMyIndex = strSource.Find ( _T("my") );
nFirstQuoteIndex = strSource.Find ( '"', nMyIndex );
nSecondQuoteIndex = strSource.Find ( '"', nFirstQuoteIndex+1 );
CString strFilename = strSource.Mid ( nFirstQuoteIndex+1, nSecondQuoteIndex-nFirstQuoteIndex-1 ); Naturally, error-checking would be a Good Thing to add to this.
--Mike--
http://home.inreach.com/mdunn/
We've secretly replaced the msdn.microsoft.com servers with Atari 800XLs. Let's see if anyone notices....
|
|
|
|
|
|
Does anyone know of a simple way to ensure that an application has only a single instance running?
When the app is clicked again the running instance should be restored and activated. I am doing all this now with an event and a background thread. It works fine but I seem to recall that there is a simpler way of doing this and I can't find it anywhere.
Apropos, is it possible to send a windows message, like WM_SHOWWINDOW, between applications rather than within an application?
By the way I have no problem getting the PID or the window handle if they are needed for the solution.
Have Fun all.
|
|
|
|
|
Re Q1:
In 16 bit windows, which was an 'all one process' affair, you could check the hInstance param passed to the entry fn to do this.
Nowadays, the de jure standard is to use shared memory - a named memory mapped file (see CreateFileMapping and MapViewOfFile ) that the app creates on startup - if it already exists, exit, perhaps passing control to the first instance.
There was an excellent intro to this stuff in Jeff Prosise's Wicked Code MSJ November 1998.
A background thread approach sounds interesting though.
|
|
|
|
|
and remember we went through the mutex idea here a whiles ago
---
"every year we invent better idiot proof systems and every year they invent better idiots"
|
|
|
|
|
This is the way I've done it for about 100 years now, works like a charm :
// Global declaration in CWinApp:
LPCTSTR lpszUniqueClass = _T("MyUnigueClassName");
CMyWinApp::OnInitInstance()
{
// Check status of class name...
if( DoIExist())
{
return( FALSE );
}
.
.
.
// Register our unique class name that we wish to use
WNDCLASS wndcls;
.
.
.
// Specify our own class name for using FindWindow later
wndcls.lpszClassName = lpszUniqueClass;
// Register new class and exit if it fails
if(!AfxRegisterClass(&wndcls))
{
TRACE("Class Registration Failed\n");
return FALSE;
}
.
.
.
}
BOOL CMyWinApp::DoIExist()
{
CWnd *pWndPrev, *pWndChild;
if(( pWndPrev = CWnd::FindWindow(lpszUniqueClass, NULL ) ))
{
if( pWndPrev->IsIconic() )
{
// If iconic, restore the main window
pWndPrev->ShowWindow(SW_RESTORE);
}
// if alive, does it have any popups?
if(( pWndChild = pWndPrev->GetLastActivePopup()) != NULL )
{
pWndChild->SetForegroundWindow();
}
return TRUE;
}
return FALSE;
}
|
|
|
|
|
Hi!
I tried your example, but failed to get the result. the AfxRegisterClass() always returns false. DO you know why?
I use appWizard to make my dialog base application
Thank You very much
Vu
vucsuf
|
|
|
|
|
This is where the answer is:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q243953
I found this out after failing to ask for help on this forum. I guess there are more than 1 way to do it. It just happened to me that all the solutions provided by this forum does not work for me at all.
Vu
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q243953
vucsuf
|
|
|
|
|
Great ideas but just as much work as my original. Pity that hInstance is not atomic across multi-cpu systems but that's asking a lot.
Here is my solution for anyone who is interested. I don't think its very elegant but it works.
At the beginning of xxxApp::InitInstance()look for an event.
BOOL CTestApp::InitInstance()
{
// See if an instance of myself is already running
if (( eDoIExist = OpenEvent( EVENT_ALL_ACCESS, NULL,
"YesIExist" )) != NULL )
{
// Yes. There is someone out there. Wake it up.
SetEvent( eDoIExist );
// And get out
return FALSE;
}
// No. I am the first so set up an event.
eDoIExist = CreateEvent( NULL, TRUE, FALSE, "YesIExist" );
..... Later in the init code when the main window (in my case a dialog) is
..... set up
CTestDlg dlg;
m_pMainWnd = &dlg;
// Create a background thread to look for any other instance and send it
// the main window
::CreateThread( NULL, 0, LookForMyself, m_pMainWnd , 0, NULL );
..... At the end of the same source
DWORD WINAPI LookForMyself( LPVOID lpParameter )
{
// Forever
do
{
WaitForSingleObject( eDoIExist, INFINITE );
// This is just a little flashy way of re-activating the running
// instance
((CDialog *)lpParameter)->ShowWindow( SW_SHOWMINIMIZED );
((CDialog *)lpParameter)->ShowWindow( SW_RESTORE );
// Reset and wait for more intruders
ResetEvent( eDoIExist );
} while ( TRUE );
return 0;
}
Thank you all for your responses!
|
|
|
|
|
You could use a mutex to check if you are the first instance, and if not send a app specific message with BroadcastSystemMessage().
(never actually tried it, but i think it should work and be quite a simple solution)
|
|
|
|
|
Maybe the mutex is not even needed, sending the app specific message with BroadcastSystemMessage() and the flag BSF_QUERY and checking the retval might do the trick.
|
|
|
|
|
Great ideas people! I am going to try all of these just to see what works and what don't.
|
|
|
|