The CSystem Class and the System Object


Visual Basic provides some useful global objects—App, Printer, and Screen—but, until now, it lacked a System object to tell you everything you need to know about your environment. In Chapter 5, I explained what makes the System object the one and only instance of the CSystem class in VBCore. Now I’ll discuss what the System object does.


The System tab of the All About program in Figure 11-1 shows the information you can get from the System object. These properties fall into one of two cate-gories. Some pieces of information—such as the operating system version and the processor—never change, at least not while a program is running. For this kind of information, CSystem gets all the data it needs in Class_Initialize and stores it in private variables.

Private Sub Class_Initialize()
Dim dw As Long, c As Integer
dw = GetVersion()
iWinMajor = dw And &HFF&
iWinMinor = (dw And &HFF00&) / &H100&
sMode = IIf(dw And &H80000000, "Windows 95", "Windows NT")
GetSystemInfo sys
End Sub

You can then access this data through Property Get procedures such as the following:

Property Get WinMajor() As Integer
WinMajor = iWinMajor
End Property

Other pieces of information—the amount of memory available, for instance—change all the time and must be calculated on request in Property Get ­procedures.

Property Get MemoryLoad() As Long
Dim mem As MEMORYSTATUS
mem.dwLength = Len(mem)
GlobalMemoryStatus mem
MemoryLoad = mem.dwMemoryLoad
End Property

Rather than explain the memory information returned by the System object, I’m going to explain what it doesn’t return—system resources. Under 16-bit systems, information about remaining resources could predict your success in launching an additional application or tell you why an application that usually works is going haywire today. Fortunately, that’s generally not a problem for today’s 32-bit systems. Between real and virtual memory, there’s usually enough memory, and if there isn’t, interpreting what the GlobalMemoryStatus API function returns about physical memory, virtual memory, and the size of the swap file is a black art.


The System object returns all the information, but the numbers are a moving target. What you really want to know is whether your next big memory ­allocation is going to slow your machine to a thrashing, grinding crawl. The MemoryLoad property of the System object purports to give you a general idea of your memory use as a percentage of total memory, but I’ve found this number to be completely unreliable under Windows 95. I don’t trust its magic formula based on undocumented algorithms.


The number most users think they want is Free Resources. Windows 3.1 displayed it. Windows 95 shows it on a System Properties sheet. It must be of some use. Well, maybe. Free Resources affects only 16-bit programs. Under 16-bit Windows, memory could be allocated only in 64-KB segments. Windows used one of these segments to store all the miscellaneous data needed by the User DLL (controlling windows) and used another for data needed by the GDI DLL (controlling display graphics). When either segment got filled up, things started going wrong, and not always in very polite ways. It happened even when you had megabytes of system memory left. Fortunately, it never happens with
32-bit programs because both User and GDI get their memory out of the same big pool. It never happens to 16-bit programs under Windows NT. But Windows 95 contains a lot of old 16-bit code and some experts claim that there might be some connection between Free Resources and the performance of your 16-bit programs.


No matter what arguments I give, some of you will still ask, “Windows 95 gets them. Why can’t I?” Because you can’t thunk in Visual Basic. The Win32 API doesn’t provide any way to get Free Resources because all resources are free, but Windows 95 gets them anyway by using a complicated process called thunk­ing to call 16-bit Windows API functions from 32-bit code. Thunking is documented with assembly language examples in the Win32 Software Development Kit. I’ve never seen it done in C, much less in Visual Basic. But if you have a copy of Visual Basic version 4 hanging around, thunking is easy. Just create a 16-bit ActiveX EXE component that calls the Windows 3.1 GetFree­SystemRe­sources function and returns the value as a property. You can then load this server from your 32-bit program and use the properties. I don’t recommend this, and I don’t support it in my System object. But if your client insists, that’s how you can deliver.