|
Thanks for that Roger. Using a mousehook to imitate a draggable menu, and the WM_CANCELMODE lets
me do what I want. Rather a roundabout method, but it works...
I can feel a flurry of small articles coming on from this pet project. I had to write a
FindMenuItemFromPoint function while may prove useful to others. Or not!
Iain.
|
|
|
|
|
I'm want to make a control that can be used in VB and I'm wondering what the best approach would be? Would it be best to use MFC, ATL, something else? The control wont have any UI. Thanks for any tips, suggestions, help.
- Aaron
|
|
|
|
|
ATL. There's no such thing as MFC interop with VB.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
What is your control supposed to do ?
What operations does it need ?
Does it have a message pump ?
If it doesn't have an UI, what is it's purpose ?
You could consider developing a COM component. Such component can be easily used in VB, without much effort. Windowless (UI-less) controls are common in the ActiveX world, so ATL would be a valid approach also. Using ATL offers platform-independence and smaller executables than MFC, which also requires the correct version of MFC Runtime installed.
So, for a coherent answer: develop an ATL control without a window. You can use it easily in VB by just registering the component, referencing it in VB, then utilizing it. I have little experience in using COM components in VB (or VB altogether), so I can't give you any definite steps on how to utilize the component in VB.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
I'm trying to create dynamic menus with MFC's MDI interface. I've used CMenu's AppendMenu() or InsertMenu() function to insert a popup menu at the end of another menu in the MainFrame. The problem is that this works when the ChildFrame is first expanded when I create the menus, but if I try to create the menus when the ChildFrame is not expanded, they are not created properly. I read in the MSDN documentation that this is because the offsets of the menus are shifted by one when the MDI window is expanded. Therefore, I attempted to fix the code so it isn't position dependant, but this didn't seem to work. I think I don't understand the menu placement quite right. If anyone knows more about this, could you see where I'm going wrong in this code below and let me know?
Here's where I create the dynamic menu:
void CDoc::AddMenuUpdate()
{
CString sAddChan;
CMenu* pConfMenu = NULL;
CMenu* pTopMenu = AfxGetMainWnd()->GetMenu(); // Will this get the right top-level menu?
// Locate the configuration submenu to put the popup menu under
for (int iPos = pTopMenu->GetMenuItemCount()-1; iPos >= 0; iPos--)
{
CMenu* pMenu = pTopMenu->GetSubMenu(iPos);
if (pMenu && pMenu->GetMenuItemID(0) == ID_PROJECT_PROJECTSETUP)
{
pConfMenu = pMenu;
break;
}
}
ASSERT(pConfMenu != NULL);
// If a popup menu already exists, remove it to replace it with an updated one.
for (int iAddPos = pConfMenu->GetMenuItemCount()-1; iAddPos >= 0; iAddPos--) {
CMenu* pAddMenu = pConfMenu->GetSubMenu(iAddPos);
if(pAddMenu && pAddMenu->GetMenuItemID(0) == ID_CHANOFFSET) {
if(!pConfMenu->DeleteMenu(iAddPos, MF_BYPOSITION)) {
TRACE(_T("Error removing the existing popup menu..."));
}
break;
}
}
mAddCmds.clear(); // clear out the old command to hierarchy mappings
// And then create and add the new popup menu
CMenu addMenu;
VERIFY(addMenu.CreatePopupMenu());
VERIFY(pConfMenu->AppendMenu(MF_POPUP, (UINT)addMenu.m_hMenu, _T("Add Channel")));
// Get the list of items to add to the menu...
int iLoc = 0;
for(int i = 0; i < NEW_MENU_CMDS; i++) {
mAddCmds.insert(std::make_pair(ID_CHANOFFSET + iLoc, i));
// For each heirarchy, add an item to the popup menu
addMenu.AppendMenu(MF_STRING | MF_ENABLED, ID_CHANOFFSET + iLoc, "Genero Menu Cmd");
++iLoc;
}
HMENU hMenu = addMenu.Detach(); // Do I need to detach this here? Will it make a copy when I insert it into the pConfMenu?
}
|
|
|
|
|
I am in the process of writing an article which covers many of the areas your question covers.
The main issue is:
When you get a menu from the mainframe, it has a system menu inserted at the front of it. So if you did GetSubMenu(0) on it you would get the system menu when the menu was in use (one of the documents of that type were active) or the File menu (if none of the doucment types were active).
The best way to do what you need is to go directly to the CDocTemplate::m_hMenuShared member and modify the menu. If you do the mods in the InitInstance() of your app before the menu is officially used, then all your dynamic changes will be picked up correctly.
I wrote a nice function to do menu iserting to any popup level, but its not on my work PC. I may get chance to post it tonight
Roger Allen - Sonork 100.10016
Strong Sad:
Clever I am? Next to no one.
Undiscovered and soggy.
Look up. Look down. They're around.
Probably laughing. Still, bright, watery.
Listed among the top. Ten.
Nine. Late night. Early morn.
Early mourn. Now I sleep.
|
|
|
|
|
A while ago, I posted a question concerning the problems a customer was seeing related to this message. The destination window was recieving a bad pointer to the data that WM_COPYDATA sends. The solution was to remove the NVIDIA tray application. Once that was done, the problems went away.
Now, I'm seeing the exact same problem with XP when I use "WindowBlinds" by Object Desktop. When it is loaded (doesn't matter which skin I use), the WM_COPYDATA pointer is bogus.
Any idea what is going on here? Why do these programs affect the way the WM_COPYDATA operates?
|
|
|
|
|
I saw a similar situation many years ago where a 3rd party DLL that we were using had installed a hook of some sort. That hook was intercepting messages, but not passing them on to the next message queue in the chain. Our application never saw the messages. Once we removed that DLL from the picture, all was well.
"The pointy end goes in the other man." - Antonio Banderas (Zorro, 1998)
|
|
|
|
|
I'm writing a MFC program in Visual Studio 6.0. When I run it on my Windows XP cumputer it works great, but if I try it on my other computer with Windows 98 the program starts to "eat" memory at a very fast rate.
I have traced the problem to the following function (if I comment it out the program stops using up all the memory on the Windows 98 computer)
CClientDC dc(this);
CDC buffer;
buffer.CreateCompatibleDC(&dc);
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, SKARM_BREDD, SKARM_HOJD);
buffer.SelectObject(&bitmap);
CBrush vit(RGB(255, 255, 255));
CRect rect(0, 0, SKARM_BREDD, SKARM_HOJD);
buffer.FillRect(&rect, &vit);
for(int i = 0; i < sidor.size(); i++)
{
buffer.MoveTo(skarmKoord.at(sidor.at(i).hornPunkter.at(0)));
for(int j = 1; j < sidor.at(i).hornPunkter.size(); j++)
buffer.LineTo(skarmKoord.at(sidor.at(i).hornPunkter.at(j)));
buffer.LineTo(skarmKoord.at(sidor.at(i).hornPunkter.at(0)));
}
dc.BitBlt(5, 5, SKARM_BREDD, SKARM_HOJD, &buffer, 0, 0, SRCCOPY);
Is it something wrong with this code?
|
|
|
|
|
jonsson_84 wrote:
When I run it on my Windows XP cumputer it works great... with Windows 98 the program starts to "eat" memory...
How are you verifying these?
jonsson_84 wrote:
buffer.SelectObject(&bitmap);
Where is the call to restore the bitmap?
"The pointy end goes in the other man." - Antonio Banderas (Zorro, 1998)
|
|
|
|
|
Actually I don't know if Windows 98 is the problem. I can hear when Windows starts to swap memory to the hardsisk.
I don't restore the bitmap. Is that the problem? How do I restore it?
Update: I have tried it on one more Windows 98 computer now, the results are the same.
|
|
|
|
|
jonsson_84 wrote:
I can hear when Windows starts to swap memory to the hardsisk.
Hardly a valid test, don't you think? While increased disk activity does indicate something is happening, without the proper tools in place, it would be really hard to pinpoint anything specific.
"The pointy end goes in the other man." - Antonio Banderas (Zorro, 1998)
|
|
|
|
|
Of course I know that many things can increase the disk activity but it "felt" like a memory leak and it seems like I was right.
|
|
|
|
|
You must unselect bitmap from buffer , you are leaking GDI-resources.
Change:
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, SKARM_BREDD, SKARM_HOJD);
buffer.SelectObject(&bitmap);
to
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, SKARM_BREDD, SKARM_HOJD);
CBitmap* oldbitmap = buffer.SelectObject(&bitmap);
and add (after the BitBlt )
buffer.SelectObject( oldbitmap );
|
|
|
|
|
It works now.
Thanks for the help!
|
|
|
|
|
Hi all,
I am trying to allow users to configure their printers from a web page. I am thinking of referencing an activeX control inside my asp.net page to then allow user to configure their printers.
Requirements
I want the user to setup three different printing schemas (one for reports, one for receipts, etc.) . I also want these settings to be specific to the workstation and global for all users using the same configurations.
Is an ActiveX control available (third-party) or some code I could reference ?
Any advice appreciated.
(I didn't really no where this post fit in, so I put it here)
R.Bischoff
.NET, Kommst du mit?
|
|
|
|
|
I am having trouble with linking files due to global class objects. What is the best way to define them and not having to use extern in other header files?
Will making a CPP file specifically for these global class objects work (I would try this myself but since my very long code is now cluttered and in need of re-writing I can't test it without spending a couple of days of re-writing)
|
|
|
|
|
What do you mean by "global class objects?" Are you wanting an instance of a class that is accessible in more than one file? I would think that using the extern keyword would work best here. Do you have reservations about its use?
"The pointy end goes in the other man." - Antonio Banderas (Zorro, 1998)
|
|
|
|
|
Yes, that's exactly what I mean. I don't have a specific problem using it but I wanted to have one file where everything global is defined so I wouldn't have to go into every file and use extern in its header. Is this possible at all?
|
|
|
|
|
yes, it is possible.
Here's one way :
#ifdef DECLARE_GLOBALS
#define Global
#else
#define Global extern
#endif
class CMyClass
{
...
};
Global CMyClass g_GlobalObject;
then place the definition :
#define DECLARE_GLOBALS
in one and ONLY one file, before it includes the header declaring CMyClass.
__________________________________________
a two cent stamp short of going postal.
|
|
|
|
|
Use a common header file, with the extern keyword, that is included by every implementation file. For example, MFC uses 'stdafx.h' file to include all common Windows/MFC/Sockets/ODBC/Whatever header files required in all files.
Of course, you need to use a pragma definition (#pragma once), otherwise you might get multiple-declaration errors.
Always remember, though that having too many global objects is a sure way to invite trouble in the house. Put only those variables global that MUST be, use class members and pointers to class members elsewhere whenever possible. For example, if I have a dialog that has a list control, my database class might have a direct pointer to this control, allowing manipulation where necessary.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
OK, this is something that I was thinking of. Let me try to understand this. Make a header file and include the global class objects as externs, then include this header file in every cpp file that needs to use those objects.
I don't understand the final step. Does it have to be clearly defined in one file as not extern? If so, is this where #pragma comes in?
|
|
|
|
|
I generally find it problematic to put variable declarations (as opposed to definitions) into header files. The tricks suggested about using #ifdef... are really just to trick the compiler into accepting a generally ill-advised way of writing code.
My suggestion is to declare your global variables in the source file where they are originally created, not in a header file, and then every other source file that needs access to the global variables needs to use extern . For these other source files, they can #include a GlobalVars.h file that simply contains all of the necessary extern statements for the global variables. The main source file does not #include GlobalVars.h, as it is the file that is declaring them.
The advantage to this approach is that variables (and the access to them) is not hidden through a set of #include , #define , and #ifdef statements. You are writing exactly what you want in a straightforward way that will be less prone to error and easier to understand.
While it makes no difference to the compiler, it will be more understandable to anyone reading the code.
Dave
"You can say that again." -- Dept. of Redundancy Dept.
|
|
|
|
|
I am trying to write a small program in VC++7 (win32 console app) that invokes BIOS and DOS interrupts. I am taking an assembly langiage class, and I can add __asm blocks, but the program crashes whenever int 10h, int21h or int 33h is called. Apparently VC7 does not support the int86 function for calling interupts. Can anyone help with this
'
James Meade
vLT(jg) vUSN
vOPSOFF VAQ-140
|
|
|
|
|
If you're using Windows NT, Windows 2000, or Windows XP then using DOS interrupts directly are going to give you problems because those versions of Windows don't use DOS.
Jeremy Falcon
|
|
|
|