|
I have a problem in my (nonMFC) app, in that when I get a Window rect, it does not appear to take into account the size of the caption or the menu. A further problem is that the menu sometimes takes up more than one line, when the dialog is resized, and so I need to know how many rows there are before I can use SM_CYMENU or whatever it is, to get the correct value.
Can anyone point me in a direction that is not circular ?
Christian
I have come to clean zee pooollll. - Michael Martin Dec 30, 2001
Sonork ID 100.10002:MeanManOzI live in Bob's HungOut now
|
|
|
|
|
Hi Christian,
Can you do (this just being a guess):
RECT vrClient;
RECT vrWindow;
POINT vpTopLeft;
GetClientRect(m_hWnd, &vrClient);
GetWindowRect(m_hWnd, &vrWindow);
vpTopLeft.x = vrClient.left;
vpTopLeft.y = vrClient.top;
ClientToScreen(m_hWnd, &vpTopLeft);
Hope this helps.
------------------------
Derek Waters
derek@lj-oz.com
|
|
|
|
|
Hi ,
Is it possible to load other ActiveX controls from one ActiveX Control at
run time.
The ActiveX control I have to develop..whose responsibility is to load
the other activeX controls and PASS parameters they require at run time
The parameters I have to pass and the class ID of the control I will be
getting
from the html page in which my activeX control is present.
For Example:
<html>
<head>
</head>
<object classid="CLSID of My ActiveX control" width="300" height="250">
<param name "TotalControlsToLoad" value ="N">
<param name "Control ID" value ="ToLoad1">
<param name="Control ID" value= "ToLoad2">
.......................
.......................
<param name="Control ID" value= "ToLoad N">
</object>
<object classid="CLSID of Some Active X control One" ID="ToLoad1">
</object>
<object classid="CLSID of Some Active X control two" ID ="ToLoad2">
</object>
</body>
</html>
1. Is it possible to for my ActiveX control to get the information of other
activeX controls in the HTML page.
2. Is it possible to load the other active X controls using my control.
3. How do I communicate with other ActiveX controls...
i.e I know control communicates with container...But how do two controls
which are
contained in the same container communicate with each other.
Please send your Inputs/Suggestions /Improvements.
Thanks in Advance,
Raju
|
|
|
|
|
I've got a dialog-based app with a button that plays a .wav file when the button is pressed. It works fine, but a problem is that if you press the button multiple times while the .wav file plays, it plays the .wav file that many times over and over. I've tried disabling the button during the play, but I think the mouse-click message isn't received by the object until after the play is over, so even though the button is disabled, I can still click a second time during the play and it will play again after the first play is over...if that made sense.
Here is what I tried. Despite all this, the .wav still plays twice if I click the button twice:
void CWaveTestDlg::OnPlay()
{
if (isPlaying) return;
isPlaying = TRUE;
CWaitCursor wc;
CButton* pPlayButton;
pPlayButton = (CButton*) GetDlgItem(IDC_PLAY);
pPlayButton->EnableWindow(FALSE);
// code to play wave file
isPlaying = FALSE;
pPlayButton->EnableWindow(TRUE);
}
I've also tried overloading the WM_LBUTTONDOWN message and not
calling the base class if we isPlaying, but this didn't work
because OnLButtonDown only receives clicks from the dialog window
itself, not the button.
void CWaveTestDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
if (!isPlaying)
CDialog::OnLButtonDown(nFlags, point);
}
Any help is appreciated!
|
|
|
|
|
The OnPlay code will work if the "code to play wave file" is synchronous. My suspicion is that it starts playing the wave file and then continues to the code that re-enables the Play button again.
Have you run this through the debugger?
You don't show the code to play the wave file, but take a look at the sndPlaySound function to which you can pass the SND_SYNC flag.
Regards,
Alvaro
|
|
|
|
|
Try insert next code into the OnPlay()
...
pPlayButton->EnableWindow(FALSE);
MSG message;
if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
::TranslateMessage(&message);
::DispatchMessage(&message);
}
...
Best regards,
Eugene Pustovoyt
Sonork ID 100.10002:Yaumen
|
|
|
|
|
I believe that what is happening here is that the button gets enabled before the wave finishes playing, probably because your play-wave-whatever function returns immediately and the wave is actually played in the background
Nish
Sonork ID 100.9786 voidmain
www.busterboy.org
If you don't find me on CP, I'll be at Bob's HungOut
|
|
|
|
|
Thanks for all your ideas...
I'm using the mciSendCommand fuction with the MCI_WAIT flag so that it doesn't return until the play is done. This seems to work because the button grays out while its playing and then is re-enabled after the play stops. Nevertheless, I can still click again on the grayed-out button while the .wav is playing and it will play again after it finishes.
I tried to insert the ::PeekMessage code with no results.
I'll look into the sndPlaySound function also, but maybe I can solve this from another approach. I copied my play wave function out of the MSDN help files for MCI, but didn't know how to handle the notify message in my dialog. Maybe someone could help me with this and it would solve the problem? Here's my complete code:
void CWaveTestDlg::OnPlay()
{
if (isPlaying) return;
isPlaying = TRUE;
CWaitCursor wc;
UpdateData(TRUE);
if (m_wave.GetLength() <= 0)
{
AfxMessageBox("Please enter a wave file name.");
return;
}
CButton* pPlayButton;
pPlayButton = (CButton*) GetDlgItem(IDC_PLAY);
ASSERT(pPlayButton != NULL);
pPlayButton->EnableWindow(FALSE);
LPTSTR pStr = m_wave.GetBuffer(0);
CString msg;
MCIERROR mciErr;
if (mciErr = playWAVEFile((HWND) this, pStr))
{
char errStr[128];
LPTSTR pErrStr = errStr;
if (mciGetErrorString(mciErr, pErrStr, 128))
msg.Format("Unknown Error playing Wave File");
else
msg.Format("Error playing wave file : %s", pErrStr);
AfxMessageBox(msg);
}
isPlaying = FALSE;
pPlayButton->EnableWindow(TRUE);
pPlayButton->SetFocus();
}
DWORD CWaveTestDlg::playWAVEFile(HWND hWndNotify, LPSTR lpszWAVEFileName)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_PLAY_PARMS mciPlayParms;
mciOpenParms.lpstrDeviceType = "waveaudio";
mciOpenParms.lpstrElementName = lpszWAVEFileName;
if (dwReturn = mciSendCommand(0, MCI_OPEN,
MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)(LPVOID) &mciOpenParms))
{
return (dwReturn);
}
wDeviceID = mciOpenParms.wDeviceID;
// Begin playback. The window procedure function for the parent
// window will be notified with an MM_MCINOTIFY message when
// playback is complete. At this time, the window procedure closes
// the device.
mciPlayParms.dwCallback = (DWORD) hWndNotify;
if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_WAIT,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
//I inserted this next line so that the device is
//closed from within the function...cause I didn't know how
//to handle the callback notification message.
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (0L);
}
Thanks!
|
|
|
|
|
> I'll look into the sndPlaySound function also, but maybe I can solve this from another approach
Setting SND_SYNC will not help you, that is the default behaviour (the value of that flag is zero). I believe what is happening is the following:
1: You disable the button
2: You play the sound, which blocks the application (including the message pump)
3: The user queues up a button press by clicking on it while your application is blocked (you are not pumping messages)
4: Your sound finishes, and you enable the button
5: You return from the function and the message pump starts running again
6: The button click message is received, and you go back to #1
EnableWindow(...) sends a WM_ENABLE message, likely through a SendMessage(...) call, and anyone that knows Win32 should know that SendMessage(...) will bypass the message pump under certain conditions, which is what I believe is happening here. So the Enable and Disable "messages" are being processed before the queued button press.
> I tried to insert the ::PeekMessage code with no results.
That will not work, because it only checks for one message, and only processes one message if it finds one. By the time the user clicks on the button, the PeekMessage(...) code is long since past.
My suggestion would be to use the MCI functions' ability to send a notification message (MM_MCINOTIFY) to you when the sound finishes. You disable the button, play the sound Async. (do not specify the MCI_WAIT flag), and enable the button when you get the notification message that the sound has finished playing.
Peace!
-=- James.
|
|
|
|
|
James,
I figured out how to handle the MM_MCINOTIFY message and that is exactly what I needed.
I added this line to my main dialog message map:
ON_MESSAGE(MM_MCINOTIFY, OnNotifyWavDone)
I added this line to my header file after my class-wizard generated message map functions:
afx_msg LRESULT OnNotifyWavDone(WPARAM wParam, LPARAM lParam);
and I call the MCI function from my main dialog like so:
mciPlayParms.dwCallback = this->GetSafeHwnd();
if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
This closes the device only if there is an error, otherwise, the closing and re-enabling of the button are handled in the callback function:
LRESULT CWaveTestDlg::OnNotifyWavDone(WPARAM wFlags, LPARAM lDeviceID)
{
switch(wFlags)
{
case MCI_NOTIFY_SUCCESSFUL:
m_outputString.Format(_T("Playback completed"));
break;
case MCI_NOTIFY_FAILURE:
m_outputString.Format(_T("Playback interrupted!"));
break;
case MCI_NOTIFY_SUPERSEDED:
m_outputString.Format(_T("Playback stopped!"));
break;
}
mciSendCommand(lDeviceID, MCI_CLOSE, 0, NULL);
isPlaying = FALSE;
CButton* pPlayButton;
pPlayButton = (CButton*) GetDlgItem(IDC_PLAY);
ASSERT(pPlayButton != NULL);
pPlayButton->EnableWindow(TRUE);
pPlayButton->SetFocus();
UpdateData(FALSE);
return 0L;
}
Thought it might be useful to someone. I found some helpful example code here:
http://www.codeguru.com/multimedia/cd_audio.shtml#1
Thanks much,
Eric
|
|
|
|
|
Eric Jacobsen wrote:
I figured out how to handle the MM_MCINOTIFY message and that is exactly what I needed. Thanks much,
No problem. Glad I was able to help.
Peace!
-=- James.
|
|
|
|
|
CString str = "dd.rr.hh";
Now, how to search that string after dd, rr and hh and save them into a separete CString?
I know how to look up if I found the '.' in the string and after finding the dot I assign a CString dd (all characters that I've found till I found the dot) into anothr CString. But when I then want to keep search for rr (keep search after the dot) I don't know how to restart the loop... hmm
------------------------------
©0d3 ©®4©k3® - That's me!
------------------------------
|
|
|
|
|
You can use strtok, or you can just grab the index from the search and then do a new search starting from that index + 1, unless the search is not successful, or you've reached the end of the string.
Christian
I have come to clean zee pooollll. - Michael Martin Dec 30, 2001
Sonork ID 100.10002:MeanManOzI live in Bob's HungOut now
|
|
|
|
|
Let me take a rough stab at this. Note that this may not compile but it should give you some ideas as to what you can do to solve this kind of problem.
CString str = "dd.rr.hh";
CString strParts[100];
CString strSearch = str;
for (int iPart = 0; iPart < 100; iPart++)
{
int nPos = strSearch.Find('.');
if (nPos < 0)
{
strParts[iPart] = strSearch;
break;
}
strParts[iPart] = strSearch.Left(nPos);
strSearch = strSearch.Mid(nPos + 1);
}
You should end up with the strParts array containing the distinct parts in the first 3 elements.
Now, as an exersice I recommend you write yourself a global function that takes two CString arguments. The first is the value to parse, the second is the delimitter to parse with. The return value should be a CStringArray object containing the parsed elements.
Regards,
Alvaro
|
|
|
|
|
Why would you go to the effort when strtok does exactly the same thing ( assuming you want to pass CStrings and *not* use the built in find functions ), and why would *anyone* use CStringArray ?
Christian
I have come to clean zee pooollll. - Michael Martin Dec 30, 2001
Sonork ID 100.10002:MeanManOzI live in Bob's HungOut now
|
|
|
|
|
As that old Bud Dry commercial goes, "Why ask why?"
I answered the guy's question and gave him a solution. It's not your solution, but then again, I didn't say it was better than yours. It's just an alternative. Does it work? Yes! Then why ask why?
Well, for one, strtok has the "not-thread-safe" stigma. Another thing, strtok doesn't do *exactly* the same thing. You have to call it twice inside a loop, and with different parameters. I personally find it a somewhat confusing function to use. It's just not as straight-forward as the code I wrote.
Now as for the CStringArray class... woah, a class that encapsulates an array of CString objects. Gee, that sounds like the most *useless* class possible for storing CString objects inside an array! I really really ought to consider alternatives, like the STL classes. Those are really intuitive and well documented, right? That's what I thought.
Regards,
Alvaro
|
|
|
|
|
Woah - no need to come out swinging !!!
Alvaro Mendez wrote:
I answered the guy's question and gave him a solution. It's not your solution, but then again, I didn't say it was better than yours. It's just an alternative. Does it work? Yes! Then why ask why?
Effeciency ? Ultimately, if you have a CString, why not use the functions CString provides to do such things ? If you're not going to use them, there's no reason not to prefer std::string.
Alvaro Mendez wrote:
Now as for the CStringArray class... woah, a class that encapsulates an array of CString objects. Gee, that sounds like the most *useless* class possible for storing CString objects inside an array! I really really ought to consider alternatives, like the STL classes. Those are really intuitive and well documented, right? That's what I thought.
Yes, they ARE intuitive, and despite M$ giving you no real help with them, there is great help available online at the STL site, and also a number of very good books.
So you've got your CStringArray. Now sort it. Sort it again, randomly. Now provide me with all available permutations. Ooops. Looks like the STL wins out again.
Christian
I have come to clean zee pooollll. - Michael Martin Dec 30, 2001
Sonork ID 100.10002:MeanManOzI live in Bob's HungOut now
|
|
|
|
|
OK OK, no need to fuss over which solution is better here.
I just think CString and CStringArray can satisfy our needs over 90% of the time. They're part of MFC, they're used and supported by other MFC classes, and they're well documented by Microsoft. So I say use them, especially if you're just getting into MFC.
STL is a fine library, except for 2 things: 1) it's not well documented by Microsoft, and 2) it's not all that intuitive, especially when it comes to function names. Sure, once you start getting the hang of it and know where to find its documentation, it's fine. But you could just as well go with the MFC counterparts and do equally fine, in less time.
As far as sorting goes, nope, you can't sort a CStringArray directly. I actually wrote some pretty nifty functions that do it using the qsort function, but that's beside the point. STL is great for that and more, but then again... how many of us need to sort arrays of strings inside our programs? In my 10 years of Windows development, I think I've only done it twice - hence my nifty functions.
Perhaps the best reason to use STL is multi-platform support. That's where STL reigns supreme. But for Windows development, I still favor the MFC classes.
Regards,
Alvaro
|
|
|
|
|
Hey. I'm making a program in Windows API in C++ (not MFC). I'm trying to add picture files onto buttons, or just on the form and when you click them, it processes an event.
Any help on how to load a .gif or any picture file onto a form or button? Thanks =)
Dave
|
|
|
|
|
You can use GDI+ to load a gif. You can use ::LoadImage to load a bmp from disk or resources. Then make the button owner drawn, and draw the bitmap onto it using the WM_DRAWITEM message. You can use an STL map to map the windows HWND to a bitmap to avoid global data, or better yet, wrap your buttons in a class and map the HWND to the pointer to the class instance.
Christian
I have come to clean zee pooollll. - Michael Martin Dec 30, 2001
Sonork ID 100.10002:MeanManOzI live in Bob's HungOut now
|
|
|
|
|
Is there any way to mimic the behavior of PrintInsideRect() when printing from a CScrollView?
Printing... what a pain.
|
|
|
|
|
Yes, do the printing yourself
Catch OnPrint in your derive CScrollView.
- God bless the World
|
|
|
|
|
Any guidance on how to tell programatically whether Visual C++ is running? The simplest solution would appear to be if there is a known mutex that I could refer to, but I have had no luck finding any such information in MSDN or on the web.
Failing that, other suggestions also welcome. It's with a view to writing installer(s) using Martijn Laan's "My Inno Setup Extensions", so I can write an extension DLL in C++ if necessary.
Cheers,
Gavin Greig
|
|
|
|
|
You need to Use PSAPI Functions.
Start with ProcessEnum Function...
I wrote a class that Do that you need...
If you want for a I can share the class with you....
Best Regards
Carlos Antollini.
Sonork ID 100.10529 cantollini
|
|
|
|
|
Also you can See what Applications Are running enumming the HWND...
Also I Wrote a Class that Do that....
The Principal difference is that for PSAPI functions you need the psapi.dll that is only in NT and W2K, Don't work under win 95/98. I don't Know what happens with XP..
Carlos Antollini.
Sonork ID 100.10529 cantollini
|
|
|
|
|