Sie sind auf Seite 1von 108

PREFACE

The library is an important module for any educational


institute. Library may contain thousands of books, and its
management is a very tough job. The care should be taken for
proper distribution of the resources. It should be managed in a
manner so that its resources are used efficiently and conveniently.
For this rules and rights should be provided to each user.

Manual management of such a large system is a very tideous


job and errors may occur sometimes. This may affect the integrity
and consistency of the system resulting in an improper resource
distribution.

Here we have provided a full-fledged library management


system, which will change the conventional manual management
with a computerized library management system. We have tried our
best to provide efficient and convenient transectory operations for
librarian and users.

We are very much thankful to all those who directly or


indirectly helped us in completing this project.

MIR MUZUMIL ALI


ASHOK KUMAR
KARTHY

b
LIBRARY SYSTEM DOCUMENATION

CONTENTS

01. ACKNOWLEDGMENT…………………………………………(a)

02. PREFACE ……………………………………………………… (b)

03. CONTENTS ………………………………………………………2

04. PROJECT SPECIFICATION …………………………………3

05. SOFTWARE STUDY ……………………………………………4

06. THE FORMS……………………………………………………… 7

07. THE DATABASE ………………………………………………… 8

08. MODULE CODING …………………………………………… 10

09. PROGRAM SOURCE CODING WITH VISUAL SHOTS … 59

10. REPORT SECTION…………………….………………………… 96

11. SETTING SECTION ……………………………………………… 98

12. SUPPORT ……………………………………………………………107

2
PROJECT SPECIFICATIONS

Project Title: LS Library Management System

Institution: A.M JAIN COLLEGE

Front End Tool: Microsoft Visual Basic 6.0

Back End Tool: Microsoft Office Access 2007

Documentation Tool: Microsoft office Word 2007

Operating System: Microsoft Windows XP

Requirements: Platform:
Microsoft Windows 9x, NT and
onwards

Hardware:
32-bit Processor, 300 MHz
32 MB RAM,
Printer

Submitted By: MIR MUZUMIL ALI.S


ASHOK KUMAR.S
KARTHY.S

Submitted To: COMPUTER SCIENCE DEPARTMENT


A.M JAIN COLLEGE
MENAMBAKKAM
CHENNAI
INDIA

3
SOFTWARE STUDY
 Software used for the development of the project are:

 Microsoft Visual Basic 6.0


 Microsoft Access 7.0

 About Visual Basic 6.0

Visual Basic developed from the old Quick Basic language that
was available under the DOS operating system. Quick Basic is
the same language as BASIC; it is just Microsoft's product name
for its version of BASIC. Visual Basic started out as the Brainchild
of Alan Cooper. Cooper developed Visual Basic and then sold the
product to Microsoft. Microsoft took the undeveloped product,
code-named it "Thunder," the proceeded to create a
programming language that would soon become one of the
premier development environments in the windows environment.

 Features Of Visual Basic

 Visual Basic is a superset of the Visual Basic for


Applications (VBA) programming language, which is
included with most of the office products.
 Includes a GUI development environment for development
Windows applications.
 Provides the ability to develop and test applications using
an interpretive run function.
 Allows for the creation of p-code and native code EXE files.
P-code is a tokenized form of your source code that will be
broken down at runtime into machine code. P-code can be
stored more efficiently and executed faster than your
source code, which is why Visual Basic will create this
intermediary form.
 Object-based development is possible using class modules.
 Rapid application development (RAD).
 Allows for the creation of COM components such as ActiveX
controls, DLLs, and EXEs.
 Has many internet development possibilities, including the
following:

1. ActiveX documents.
2. DHTML applications that help you test browser
application.
3. IIS applications that help you build server-based
application.
4. Web browser control.

4
5. FTP / HTTP support through a custom control.
6. Winsock control.
 Has an excellent integrated Help facility and Books Online?
Including good debugging facilities. It has many wizards
that help automate repetitive tasks.
 Can be extended easily through the use of Windows API
calls, hundreds of third party controls and DLLs, and
integration with other Windows applications through Com
and DCOM.
 Uses many database access methods to get at different
types of data.

 Visual Basic Advantages

 Visual Basic has many advantages over other development


languages. Here's a list of some of these advantages:

 Has A shorter learning curve and development time than


C/C++, Delphi and even Power Builder.
 Removes the complexities of the Windows API form the
programmer.
 Allows for rapid application development.
 Excellent for business applications.
 Used by most of the office suite tools as their macro
language, with the rest to follow. Other companies as well
are starting to support VBA in their products, such as
AutoCAD, Corel Draw, SAP, and many others.
 Allow you to create ActiveX controls.
 Allows you to reuse third-party controls and component, as
well as your own.
 Supplies wizards to help you learn the language as well as
to enhance your productivity with the more difficult
features of the language.
 Object oriented in nature. It's not a complete OOP
language, but it's getting closer.
 Can integrate with the Internet on both the server side and
the client side.
 Can create ActiveX Automation servers.
 Integrates with Microsoft Transaction server.
 Can run servers either on the same machine or remotely
on another computer. This allows for true distributed
processing.
 Visual Basic has a large community of developers. (More
than 3 million worldwide according to Microsoft). This
means continued support for new developers.

5
 MS Access 7.0

Microsoft Access is a powerful RDBMS tool. Microsoft Office


Access, previously known as Microsoft Access, is a relational
database management system from Microsoft that combines the
relational Microsoft Jet Database Engine with a graphical user
interface and software-development tools. It is a member of
the Microsoft Office suite of applications, included in the
Professional and higher editions or sold separately. In mid-May
2010, the current version Microsoft Access 2010 was released by
Microsoft in Office 2010; Microsoft Office Access 2007 was the
prior version. With its extensive features, it is easier to manage
large volume of database. As the project requires large database
MS ACCESS 7.0 is the perfect option as a back-end tool.
 Features of Ms Access 7.0

Users can create tables, queries, forms and reports, and


connect them together with macros. Advanced users can
use VBA to write rich solutions with advanced data
manipulation and user control.The original concept of Access was
for end users to be able to "access" data from any source. Other
uses include: the import and export of data to many formats
including Excel, Outlook, ASCII, dBase, Paradox, FoxPro, SQL
Server, Oracle, ODBC, etc. It also has the ability to link to data
in its existing location and use it for viewing, querying, editing,
and reporting. This allows the existing data to change and the
Access platform to always use the latest data. It can
perform heterogeneous joins between data sets stored across
different platforms. Access is often used by people downloading
data from enterprise level databases for manipulation, analysis,
and reporting locally.There is also the Jet Database format (MDB
or ACCDB in Access 2007) which can contain the application and
data in one file. This makes it very convenient to distribute the
entire application to another user, who can run it in disconnected
environments.One of the benefits of Access from a programmer's
perspective is its relative compatibility
with SQL (structured query language) — queries can be
viewed graphically or edited as SQL statements, and SQL
statements can be used directly in Macros and VBA Modules to
manipulate Access tables. Users can mix and use both VBA and
"Macros" for programming forms and logic and offers object-
orientedpossibilities. VBA can also be included in queries.

6
FORMS:
Login form: frmlogin.frm
Add books frmaddbook.frm
Add category frmaddcategory.frm
Add course frmaddcourse.frm
Returning books frmreturning.frm
Borrower frmborrowing.frm
Book catalog frmbookcatalog.frm
Add user frmadduser.frm
Find frmfind.frm
Main page frmmain.frm
Change password frmchangepass.frm
Add user frmuser.frm
About frmAbout.frm

7
The Database
Table: Book catalog

This table stores basic information about books; information


stored in this table is filled at the time of new book entry data
stored in this table are changed only when the table is edited.
Access No. is a field which is defined as primary key and it stores
the number by which book is uniquely identified.

Columns

Name Type Size


Access_no Text 50
Category Text 50

Table: Borrowers record

This table stores the information about all the borrowed


transaction performed. If book is issued or returned to or from staff
or student then according changes are made to the table. Access
No. is defined as primary key, other information is stored about the
staff or student by which any employee can be uniquely identified.
Columns

Name Type Size


Borrower id Text 50
Name Text 50
Mi Text 50
Status Text 50
Course Text 50
Add Text 50
Contact Number 50
8
Table: Category

This table stores the information about all the available


books.which can be added or deleted.
Columns

Name Type Size


Category Text 50

Table: charge

This table stores the overdue fees which can be increased or


decreased according library norms

Columns

Name Type Decimal place


Charge_fee Currency 2

Table: course
This table stores the courses of the book. This can be
added or deleted.

Name Type Size


Course Text 50

Table: user list

This table stores the list of users where administrator


has full access and other users had limited

Name Type Size


Username Text 50
Password Text 50

9
MODULES
Mod drawing
Option Explicit
Private Declare Function GetLastError Lib "kernel32" () As Long
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA"
(_
ByVal dwFlags As Long, lpSource As Any, dwMessageID As Long, _
ByVal dwLanguageID As Long, lpBuffer As String, _
ByVal nSize As Long, Arguments As Long) As Long
'
=============================================================
========
' APIs used primarily for drawing/graphics
'
=============================================================
========
Private Declare Function StretchBlt Lib "gdi32" ( _
ByVal hDC As Long, ByVal x As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, _
ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, _
ByVal nSrcHeight As Long, ByVal dwRop As Long) _
As Long
Public Declare Function DrawState Lib "user32" Alias "DrawStateA" (ByVal hDC
As Long, ByVal hBR As Long, ByVal lpDrawStateProc As Long, ByVal lParam As
Long, ByVal wParam As Long, ByVal x As Long, ByVal y As Long, ByVal cx As
Long, ByVal cy As Long, ByVal fuFlags As Long) As Long
Private Declare Function RealizePalette Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function CopyImage Lib "user32" (ByVal Handle As Long, ByVal
ImageType As Long, ByVal newWidth As Long, _
ByVal NewHeight As Long, ByVal lFlags As Long) As Long
Private Declare Function OleTranslateColor Lib "oleaut32.dll" _
(ByVal lOleColor As Long, ByVal lHPalette As Long, lColorRef As Long) As
Long
Private Declare Function SelectPalette Lib "gdi32" (ByVal hDC As Long, _
ByVal hPalette As Long, ByVal bForceBackground As Long) As Long
Public Declare Function GetPixel Lib "gdi32" (ByVal hDC As Long, ByVal x As
Long, ByVal y As Long) As Long
Public Declare Function GetTextColor Lib "gdi32" (ByVal hDC As Long) As Long
Public Declare Function SetTextColor Lib "gdi32" (ByVal hDC As Long, ByVal
crColor As Long) As Long
Public Declare Function SetBkMode Lib "gdi32" (ByVal hDC As Long, ByVal
nBkMode As Long) As Long
Public Const NEWTRANSPARENT = 3 'use with SetBkMode()
Private Declare Function CreatePen Lib "gdi32" _
(ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As
Long
Private Declare Function MoveToEx Lib "gdi32" _

10
(ByVal hDC As Long, ByVal x As Long, ByVal y As Long, lpPoint As
POINTAPI) As Long
Private Declare Function LineTo Lib "gdi32" _
(ByVal hDC As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function Rectangle Lib "gdi32" _
(ByVal hDC As Long, ByVal x1 As Long, ByVal Y1 As Long, ByVal X2 As
Long, ByVal Y2 As Long) As Long
' following public functions/types may not be used in these modules but are
' used in my CodeSafe program & are here for organizational reasons
Public Declare Function DrawIconEx Lib "user32" (ByVal hDC As Long, ByVal
xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As
Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal
hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long
Public Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As
Long
Public Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal
hObject As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As
Integer
Public Declare Function CreateFontIndirect Lib "gdi32" Alias "CreateFontIndirectA"
(lpLogFont As LOGFONT) As Long
Private Declare Function SystemParametersInfo Lib "user32" Alias
"SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long,
lpvParam As NONCLIENTMETRICS, ByVal fuWinIni As Long) As Long
Public Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long)
As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" _
(ByVal hDC As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function CreateBitmap Lib "gdi32" (ByVal nWidth As Long, _
ByVal nHeight As Long, ByVal nPlanes As Long, ByVal nBitCount As Long,
lpBits As Any) As Long
Private Declare Function SetBkColor Lib "gdi32" (ByVal hDC As Long, ByVal
crColor As Long) As Long
Public Declare Function GetBkColor Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function PatBlt Lib "gdi32" (ByVal hDC As Long, ByVal x As
Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal
dwRop As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, _
ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, _
ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, _
ByVal ySrc As Long, ByVal dwRop As Long) As Long
Public Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hDC As
Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal
wFormat As Long) As Long
Public Const DT_CALCRECT = &H400
Public Const DT_LEFT = &H0
Public Const DT_SINGLELINE = &H20
Public Const DT_NOCLIP = &H100

11
Private Const DT_CENTER = &H1

' Types used for fonts & images


Public Type POINTAPI
x As Long
y As Long
End Type
Public Type LOGFONT
lfHeight As Long
lfWidth As Long
lfEscapement As Long
lfOrientation As Long
lfWeight As Long
lfItalic As Byte '0=false; 255=true
lfUnderline As Byte '0=f; 255=t
lfStrikeOut As Byte '0=f; 255=t
lfCharSet As Byte
lfOutPrecision As Byte
lfClipPrecision As Byte
lfQuality As Byte
lfPitchAndFamily As Byte
lfFaceName As String * 32
End Type
Public Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type TEXTMETRIC
tmHeight As Long
tmAscent As Long
tmDescent As Long
tmInternalLeading As Long
tmExternalLeading As Long
tmAveCharWidth As Long
tmMaxCharWidth As Long
tmWeight As Long
tmOverhang As Long
tmDigitizedAspectX As Long
tmDigitizedAspectY As Long
tmFirstChar As Byte
tmLastChar As Byte
tmDefaultChar As Byte
tmBreakChar As Byte
tmItalic As Byte
tmUnderlined As Byte
tmStruckOut As Byte
tmPitchAndFamily As Byte
tmCharSet As Byte

12
End Type
Private Type NONCLIENTMETRICS
cbSize As Long
iBorderWidth As Long
iScrollWidth As Long
iScrollHeight As Long
iCaptionWidth As Long
iCaptionHeight As Long
lfCaptionFont As LOGFONT
iSMCaptionWidth As Long
iSMCaptionHeight As Long
lfSMCaptionFont As LOGFONT
iMenuWidth As Long
iMenuHeight As Long
lfMenuFont As LOGFONT
lfStatusFont As LOGFONT
lfMessageFont As LOGFONT
End Type
' Other constants used for graphics
Private Const WHITENESS = &HFF0062
Private Const MAGICROP = &HB8074A
Private Const DSna = &H220326 '0x00220326
'Color constants for GetSysColor
Public Enum ColConst
COLOR_ACTIVEBORDER = 10
COLOR_ACTIVECAPTION = 2
COLOR_ADJ_MAX = 100
COLOR_ADJ_MIN = -100
COLOR_APPWORKSPACE = 12
COLOR_BACKGROUND = 1
COLOR_BTNFACE = 15
COLOR_BTNHIGHLIGHT = 20
COLOR_BTNLIGHT = 22
COLOR_BTNSHADOW = 16
COLOR_BTNTEXT = 18
COLOR_CAPTIONTEXT = 9
COLOR_GRAYTEXT = 17
COLOR_HIGHLIGHT = 13
COLOR_HIGHLIGHTTEXT = 14
COLOR_INACTIVEBORDER = 11
COLOR_INACTIVECAPTION = 3
COLOR_INACTIVECAPTIONTEXT = 19
COLOR_MENU = 4
COLOR_MENUTEXT = 7
COLOR_SCROLLBAR = 0
COLOR_WINDOW = 5
COLOR_WINDOWFRAME = 6
COLOR_WINDOWTEXT = 8
End Enum
' local variables

13
Private m_hDC As Long ' reference to DC being drawn in
Private m_Font(0 To 1) As Long ' local copy of menu font
Private m_FontOld As Long ' font of DC prior to replacing with menu font

Public Sub DrawRect(ByVal x1 As Long, ByVal Y1 As Long, ByVal X2 As Long,


ByVal Y2 As Long)
'
=============================================================
========
' Simply draws a rectangle using the current DC's background color
'
=============================================================
========
If m_hDC = 0 Then Exit Sub
Call Rectangle(m_hDC, x1, Y1, X2, Y2)
End Sub

Public Function GetPen(ByVal nWidth As Long, ByVal Clr As Long) As Long


'
=============================================================
========
' Creates a colored pen for drawing
'
=============================================================
========
GetPen = CreatePen(0, nWidth, Clr)
End Function

Public Sub DrawCaption(ByVal x As Long, ByVal y As Long, tRect As RECT, _


ByVal hStr As String, hAccel As String, iTab As Integer, _
ByVal Clr As Long, Optional bCenter As Boolean = False, _
Optional iOffset As Integer = 0)

'
=============================================================
========
' Prints text to current DC in the coodinates & colors provided
'
=============================================================
========
If m_hDC = 0 Then Exit Sub
'Equivalent to setting a form's property FontTransparent = True
SetBkMode m_hDC, NEWTRANSPARENT
Dim OT As Long, x1 As Long
' set text color and set x,y coordinates for printing
OT = GetTextColor(m_hDC)
SetTextColor m_hDC, Clr
x1 = tRect.Right
' print the caption/text
If bCenter Then

14
DrawText m_hDC, hStr, Len(hStr), tRect, DT_NOCLIP Or DT_CALCRECT Or
DT_CALCRECT Or DT_SINGLELINE
tRect.Left = (x1 - iOffset - tRect.Right) \ 2 + iOffset
tRect.Right = tRect.Left + tRect.Right
Else
tRect.Left = x + iOffset
End If
tRect.Top = y
tRect.Bottom = tRect.Bottom + y
DrawText m_hDC, hStr, Len(hStr), tRect, DT_SINGLELINE Or DT_NOCLIP Or
DT_LEFT
If Len(hAccel) Then
' here we will print an acceleraor key if needed
tRect.Left = tRect.Left + iTab - iOffset
tRect.Top = y
DrawText m_hDC, hAccel, Len(hAccel), tRect, DT_LEFT Or DT_NOCLIP Or
DT_SINGLELINE
End If
'Restore old text color
SetTextColor m_hDC, OT
End Sub

Public Property Let TargethDC(ByVal vNewValue As Long)


'
=============================================================
========
' Maintain a local reference to the DC being drawn in
' simply prevents having to pass it to each call to a drawing routine
'
=============================================================
========
m_hDC = vNewValue
End Property

Public Sub ThreeDbox(ByVal x1 As Long, ByVal Y1 As Long, _


ByVal X2 As Long, ByVal Y2 As Long, bSelected As Boolean, _
Optional Sunken As Boolean = False)
'
=============================================================
========
' Draw/erase a raised/sunken box around the specified coordinates.
'
=============================================================
========

If m_hDC = 0 Then Exit Sub

Dim CurPen As Long, OldPen As Long


Dim dm As POINTAPI, iOffset As Integer

15
' select colors, offset when set indicates erasing
iOffset = Abs(CInt(bSelected)) + 1
If Sunken = False Then
CurPen = GetPen(1, GetSysColor(Choose(iOffset, COLOR_MENU,
COLOR_BTNHIGHLIGHT)))
Else
CurPen = GetPen(1, GetSysColor(Choose(iOffset, COLOR_MENU,
COLOR_BTNSHADOW)))
End If
OldPen = SelectObject(m_hDC, CurPen)

'First - Light Line


MoveToEx m_hDC, x1 + 2, Y2, dm
LineTo m_hDC, x1 + 2, Y1
LineTo m_hDC, X2 - 2, Y1

SelectObject m_hDC, OldPen


DeleteObject CurPen
' Next - Dark line
If Sunken = False Then
CurPen = GetPen(1, GetSysColor(Choose(iOffset, COLOR_MENU,
COLOR_BTNSHADOW)))
Else
CurPen = GetPen(1, GetSysColor(Choose(iOffset, COLOR_MENU,
COLOR_BTNHIGHLIGHT)))
End If
OldPen = SelectObject(m_hDC, CurPen)

MoveToEx m_hDC, X2 - 2, Y1, dm


LineTo m_hDC, X2 - 2, Y2
LineTo m_hDC, x1 + 2, Y2

' Replace pen & delete temp pen


SelectObject m_hDC, OldPen
DeleteObject CurPen
End Sub

Public Sub DrawMenuIcon(lImageHdl As Long, ImageType As Long, _


rt As RECT, bdisabled As Boolean, Optional bInColor As Boolean = True, _
Optional bForceTransparency As Long = 0, Optional iOffset As Integer = 0, _
Optional yOffset As Integer, Optional IMGwidth As Integer = 16, _
Optional IMGheight As Integer = 16, Optional lMask As Long = -1)

'
=============================================================
========
' Draws imagelist image on destined DC

16
'
=============================================================
========

' ensure the requested image exists


If lImageHdl = 0 Then Exit Sub

Dim lImageSmall As Long, lDrawType As Long, lImageType As Long


Const DSS_DISABLED = &H20
Const DSS_NORMAL = &H0
Const DSS_BITMAP = &H4
Const DSS_ICON = &H3
Const CI_BITMAP = &H0
Const CI_ICON = &H1
Dim rcImage As RECT

If ImageType < 2 Then


lDrawType = DSS_BITMAP
lImageType = CI_BITMAP
Else
lDrawType = DSS_ICON
lImageType = CI_ICON
End If
lImageSmall = CopyImage(lImageHdl, lImageType, IMGwidth, IMGheight,
DSS_NORMAL)
If lImageSmall = 0 Then ' failed to make a copy from the imagetype passed, try the
other settings
If lDrawType = DSS_BITMAP Then
lDrawType = DSS_ICON
lImageType = CI_ICON
Else
lDrawType = DSS_BITMAP
lImageType = CI_BITMAP
End If
lImageSmall = CopyImage(lImageHdl, lImageType, IMGwidth, IMGheight,
DSS_NORMAL)
End If
If lImageSmall = 0 Then Exit Sub

If bdisabled = False Then


' if not disabled, then straightforward extraction/drawing on coords
If ((lImageType = CI_ICON And bForceTransparency < 2) Or bForceTransparency
= 2) Then
DrawState m_hDC, 0, 0, lImageSmall, 0, rt.Left + iOffset, rt.Top + yOffset, 0, 0,
lDrawType
Else
MakeTransparentBitmap lImageSmall, rt.Left + iOffset, rt.Top + yOffset,
IMGwidth, IMGheight, , , lMask
End If
DeleteObject lImageSmall

17
Else
'
=============================================================
========
' This function is from Paul DiLascia's DrawEmbossed function
' which draws colored disabled pictures.
' To be fair to him, I modified several lines of code so
' it is customized for CodeSafe & should it fail -- not his fault
'
=============================================================
========

' // create mono or color bitmap


Dim hBitmap As Long
If bInColor Then
hBitmap& = CreateCompatibleBitmap(m_hDC&, IMGwidth, IMGheight)
Else
hBitmap& = CreateBitmap(IMGwidth, IMGheight, 1, 1, vbNull)
End If
' // draw image into memory DC--fill BG white first
' // create memory dc
Dim hOldBitmap As Long
Dim hmemDC As Long
hmemDC& = CreateCompatibleDC(m_hDC&)
hOldBitmap = SelectObject(hmemDC&, hBitmap&)
Call PatBlt(hmemDC&, 0, 0, IMGwidth, IMGheight, WHITENESS)
If (lImageType = CI_ICON And bForceTransparency < 2) Or bForceTransparency
= 2 Then
DrawState hmemDC&, 0, 0, lImageSmall, 0, 0, 0, 0, 0, lDrawType
Else
MakeTransparentBitmap lImageSmall, 0, 0, IMGwidth, IMGheight, , , lMask,
hmemDC
End If
DeleteObject lImageSmall
' // This seems to be required.
Dim hOldBackColor As Long
hOldBackColor& = SetBkColor(m_hDC&, RGB(255, 255, 255))
' // Draw using hilite offset by (1,1), then shadow
Dim hbrShadow As Long, hbrHilite As Long
hbrShadow& = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW))
hbrHilite& = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT))

Dim hOldBrush As Long


hOldBrush& = SelectObject(m_hDC&, hbrHilite&)

Call BitBlt(m_hDC&, rt.Left + 1 + iOffset, rt.Top + 1 + yOffset, IMGwidth,


IMGheight, hmemDC&, 0, 0, MAGICROP)
Call SelectObject(m_hDC&, hbrShadow&)
Call BitBlt(m_hDC&, rt.Left + iOffset, rt.Top + yOffset, IMGwidth, IMGheight,
hmemDC&, 0, 0, MAGICROP)

18
Call SelectObject(m_hDC&, hOldBrush&)
Call SetBkColor(m_hDC&, hOldBackColor&)
Call SelectObject(hmemDC&, hOldBitmap&)
Call DeleteObject(hOldBrush&)
Call DeleteObject(hbrHilite&)
Call DeleteObject(hbrShadow&)
Call DeleteObject(hOldBackColor&)
Call DeleteObject(hOldBitmap&)
Call DeleteObject(hBitmap&)
Call DeleteDC(hmemDC&)
End If
End Sub

Private Sub MakeTransparentBitmap(imgHdl As Long, _


ByVal xDest As Long, _
ByVal yDest As Long, _
ByVal Width As Long, _
ByVal Height As Long, _
Optional xSrc As Long = 0, _
Optional ByVal ySrc As Long = 0, _
Optional clrMask As OLE_COLOR = -1, _
Optional destDC As Long = 0)
'
=============================================================
========
' Borrowed and modified - creates a transparent bitmap
'
=============================================================
========

Dim hdcSrc As Long


Dim hbmMemSrcOld As Long
Dim hdcMask As Long 'HDC of the created mask image
Dim hdcColor As Long 'HDC of the created color image
Dim hbmMask As Long 'Bitmap handle to the mask image
Dim hbmColor As Long 'Bitmap handle to the color image
Dim hbmColorOld As Long
Dim hbmMaskOld As Long
Dim hPalOld As Long
Dim hdcScreen As Long
Dim hdcScnBuffer As Long 'Buffer to do all work on
Dim hbmScnBuffer As Long
Dim hbmScnBufferOld As Long
Dim hPalBufferOld As Long
Dim lMaskColor As Long
Const hPal As Long = 0

On Error Resume Next


hdcScreen = GetDC(0&)

19
If destDC = 0 Then destDC = m_hDC
hdcSrc = CreateCompatibleDC(hdcScreen)
hbmMemSrcOld = SelectObject(hdcSrc, imgHdl)
RealizePalette hdcSrc

If clrMask < 0 Then clrMask = GetPixel(hdcSrc, 0, 0)


OleTranslateColor clrMask, hPal, lMaskColor

'Create a color bitmap to server as a copy of the destination


'Do all work on this bitmap and then copy it back over the
'destination when it's done.
hbmScnBuffer = CreateCompatibleBitmap(hdcScreen, Width, Height)
'Create DC for screen buffer
hdcScnBuffer = CreateCompatibleDC(hdcScreen)
hbmScnBufferOld = SelectObject(hdcScnBuffer, hbmScnBuffer)
hPalBufferOld = SelectPalette(hdcScnBuffer, hPal, True)
RealizePalette hdcScnBuffer
'Copy the destination to the screen buffer
BitBlt hdcScnBuffer, 0, 0, Width, Height, destDC, xDest, yDest, vbSrcCopy
'Create a (color) bitmap for the cover (can't use
'CompatibleBitmap with hdcSrc, because this will create a
'DIB section if the original bitmap is a DIB section)
hbmColor = CreateCompatibleBitmap(hdcScreen, Width, Height)
'Now create a monochrome bitmap for the mask
hbmMask = CreateBitmap(Width, Height, 1, 1, ByVal 0&)
'First, blt the source bitmap onto the cover. We do this
'first and then use it instead of the source bitmap
'because the source bitmap may be
'a DIB section, which behaves differently than a bitmap.
'(Specifically, copying from a DIB section to a monochrome
'bitmap does a nearest-color selection rather than painting
'based on the backcolor and forecolor.
hdcColor = CreateCompatibleDC(hdcScreen)
hbmColorOld = SelectObject(hdcColor, hbmColor)
hPalOld = SelectPalette(hdcColor, hPal, True)
RealizePalette hdcColor
'In case hdcSrc contains a monochrome bitmap, we must set
'the destination foreground/background colors according to
'those currently set in hdcSrc (because Windows will
'associate these colors with the two monochrome colors)
SetBkColor hdcColor, GetBkColor(hdcSrc)
SetTextColor hdcColor, GetTextColor(hdcSrc)
BitBlt hdcColor, 0, 0, Width, Height, hdcSrc, xSrc, ySrc, vbSrcCopy
'Paint the mask. What we want is white at the transparent
'color from the source, and black everywhere else.
hdcMask = CreateCompatibleDC(hdcScreen)
hbmMaskOld = SelectObject(hdcMask, hbmMask)

'When bitblt'ing from color to monochrome, Windows sets to 1

20
'all pixels that match the background color of the source DC.
'All other bits are set to 0.
SetBkColor hdcColor, lMaskColor
SetTextColor hdcColor, vbWhite
BitBlt hdcMask, 0, 0, Width, Height, hdcColor, 0, 0, _
vbSrcCopy
'Paint the rest of the cover bitmap.
'
'What we want here is black at the transparent color,
'and the original colors everywhere else. To do this,
'we first paint the original onto the cover (which we
'already did), then we AND the inverse of the mask onto
'that using the DSna ternary raster operation
'(0x00220326 - see Win32 SDK reference, Appendix,
'"Raster Operation Codes", "Ternary
'Raster Operations", or search in MSDN for 00220326).
'DSna [reverse polish] means "(not SRC) and DEST".
'
'When bitblt'ing from monochrome to color, Windows
'transforms all white bits (1) to the background color
'of the destination hdc. All black (0)
'bits are transformed to the foreground color.
SetTextColor hdcColor, vbBlack
SetBkColor hdcColor, vbWhite
BitBlt hdcColor, 0, 0, Width, Height, hdcMask, 0, 0, DSna
'Paint the Mask to the Screen buffer
BitBlt hdcScnBuffer, 0, 0, Width, Height, hdcMask, 0, 0, vbSrcAnd
'Paint the Color to the Screen buffer
BitBlt hdcScnBuffer, 0, 0, Width, Height, hdcColor, 0, 0, vbSrcPaint
'Copy the screen buffer to the screen
BitBlt destDC, xDest, yDest, Width, Height, hdcScnBuffer, 0, 0, vbSrcCopy
'All done!
DeleteObject SelectObject(hdcColor, hbmColorOld)
SelectPalette hdcColor, hPalOld, True
RealizePalette hdcColor
DeleteDC hdcColor
DeleteObject SelectObject(hdcScnBuffer, hbmScnBufferOld)
SelectPalette hdcScnBuffer, hPalBufferOld, True
RealizePalette hdcScnBuffer
DeleteDC hdcScnBuffer

DeleteObject SelectObject(hdcMask, hbmMaskOld)


DeleteDC hdcMask
ReleaseDC 0&, hdcScreen

SelectObject hdcSrc, hbmMemSrcOld


RealizePalette hdcSrc
DeleteDC hdcSrc
ReleaseDC 0&, hdcScreen

21
End Sub

Public Sub SetMenuFont(bSet As Boolean, Optional hDC As Long, _


Optional bReduced As Boolean = False, Optional otherFont As Long = 0)
'
=============================================================
========
' This creates system menu fonts for the destination DC if needed
' and either sets it or removes it from the DC
'
=============================================================
========

' reference the current DC for all drawing


If hDC Then m_hDC = hDC
If bSet Then
' in order to set the font, we must first determine what it is
If m_Font(0) = 0 And otherFont = 0 Then
Dim ncm As NONCLIENTMETRICS, newFont As LOGFONT
ncm.cbSize = Len(ncm)
' this will return the system font info along with other stuff
SystemParametersInfo 41, 0, ncm, 0
' here we create a memory font based off of system menu font
newFont = ncm.lfMenuFont
m_Font(0) = CreateFontIndirect(newFont)
' now we are going to try to create a scalable font for
' separator bar text just in case the computer's menu font
' is not scalable. The following is a shortcut way of creating
' the font & I hope it works on all systems!
newFont.lfFaceName = "Tahoma" & Chr$(0)
newFont.lfCharSet = 1
newFont.lfHeight = (7.5 * -20) / Screen.TwipsPerPixelY
'newFont.lfHeight = newFont.lfHeight + 1
m_Font(1) = CreateFontIndirect(newFont)
End If
' add the font to the DC & keep reference to old font
' Calling routines responsbile for restoring original font
' with call back to this routine & a FALSE parameter
If m_FontOld = 0 And otherFont = 0 Then
m_FontOld = SelectObject(m_hDC, m_Font(Abs(CInt(bReduced))))
Else
If otherFont Then
SelectObject m_hDC, otherFont
Else
SelectObject m_hDC, m_Font(Abs(CInt(bReduced)))
End If
End If
Else
' Restoring old font
If m_hDC = 0 Then Exit Sub

22
SelectObject m_hDC, m_FontOld
End If
End Sub

Public Sub DestroyMenuFont()


'
=============================================================
========
' Simply destroy the memory font to free up resources
'
=============================================================
========
On Error Resume Next
SelectObject m_hDC, m_FontOld
DeleteObject m_Font(0)
DeleteObject m_Font(1)
m_Font(0) = 0
m_Font(1) = 0
End Sub

Public Sub DoGradientBkg(lColor As Long, tRect As RECT, hwnd As Long)


'=============================================================
==========

'=============================================================
==========

Dim sColor As String, i As Integer, tmpSB As PictureBox, formID As Long


Dim R As Integer, B As Integer, G As Integer
Dim lColorStep As Long, lNewColor As Long

On Error GoTo GradientErrors


' we are going to create a picturebox to draw the gradient in
' tried drawing directly to hdc via MoveTo & LineTo APIs, but
' everytime, it failed -- maybe Win98, maybe my graphics card?
' This works though a little slower
formID = GetFormHandle(hwnd)
' create the picture box in memory
Set tmpSB = Forms(formID).Controls.Add("VB.PictureBox", "pic___tmp_s_b",
Forms(formID))
With tmpSB
' set picturebox attributes
.Visible = False
.BorderStyle = 0
.AutoRedraw = True
.DrawMode = 13
.DrawWidth = 1
.Height = .ScaleY(tRect.Bottom, vbPixels, .ScaleMode)
.Width = .ScaleX(tRect.Right, vbPixels, .ScaleMode)
.ScaleMode = vbPixels

23
lNewColor = lColor
' loop thru each line & color it
For i = 1 To tRect.Bottom - 1
' this line is used to subtract/add colors
' for a more dramatic fade, increment the #2 below
lColorStep = (2 / tRect.Bottom) * i
' modify the current color
B = ((lNewColor \ &H10000) Mod &H100) - lColorStep
G = ((lNewColor \ &H100) Mod &H100) - lColorStep
R = (lNewColor And &HFF) - lColorStep
' ensure the Red, Green, Blue values are in acceptable ranges
If R < 0 Then
R=0
ElseIf R > 255 Then
R = 255
End If
If G < 0 Then
G=0
ElseIf G > 255 Then
G = 255
End If
If B < 0 Then
B=0
ElseIf B > 255 Then
B = 255
End If
lNewColor = RGB(R, G, B) ' cache the color & draw the line
tmpSB.Line (0, i - 1)-(tRect.Right, i - 1), lNewColor, BF
Next
' now that the gradient has been drawn, copy it to the menu panel
BitBlt m_hDC, 0, 0, tRect.Right, tRect.Bottom, .hDC, 0, 0, vbSrcCopy
End With
GradientErrors:
On Error Resume Next
' clean up
Forms(formID).Controls.Remove "pic___tmp_s_b"
Set tmpSB = Nothing
End Sub

Public Sub DrawCheckMark(pRect As RECT, lColor As Long, _


bdisabled As Boolean, Optional xtraOffset As Long = 0)
'

=============================================================
========
' Simple little check mark drawing, looks good 'nuf I think

24
'
=============================================================
========

Dim CurPen As Long, OldPen As Long


Dim dm As POINTAPI
Dim yOffset As Integer, xOffset As Integer
Dim x1 As Integer, X2 As Integer
Dim Y1 As Integer, Y2 As Integer

CurPen = GetPen(1, lColor)


OldPen = SelectObject(m_hDC, CurPen)

xOffset = 6 + xtraOffset
yOffset = pRect.Top + 6

' Here we are simply tracing the outline of a check box


' Created by opening a 8x8 bitmap editor and drawing a
' simple checkmark from left to right, bottom to top
MoveToEx m_hDC, 1 + xOffset, 4 + yOffset, dm
LineTo m_hDC, 2 + xOffset, 4 + yOffset
LineTo m_hDC, 2 + xOffset, 5 + yOffset
LineTo m_hDC, 3 + xOffset, 5 + yOffset
LineTo m_hDC, 3 + xOffset, 6 + yOffset
LineTo m_hDC, 4 + xOffset, 6 + yOffset
LineTo m_hDC, 4 + xOffset, 4 + yOffset
LineTo m_hDC, 5 + xOffset, 4 + yOffset
LineTo m_hDC, 5 + xOffset, 2 + yOffset
LineTo m_hDC, 6 + xOffset, 2 + yOffset
LineTo m_hDC, 6 + xOffset, 1 + yOffset
LineTo m_hDC, 7 + xOffset, 1 + yOffset
LineTo m_hDC, 7 + xOffset, 0 + yOffset

' replace original pen


SelectObject m_hDC, OldPen
DeleteObject CurPen
End Sub

Mod global
Public libCON As ADODB.Connection
Public borrowerRS As ADODB.Recordset
Public catRS As ADODB.Recordset
Public bookRS As ADODB.Recordset
Public borrowRS As ADODB.Recordset
Public currentRS As ADODB.Recordset
Public courseRS As ADODB.Recordset
Public returnRS As ADODB.Recordset
Public feeRS As ADODB.Recordset
Public userRS As ADODB.Recordset

25
Public returnCMD As ADODB.Command
Public bookCMD As ADODB.Command
Public borrowerCMD As ADODB.Command
Public currentCMD As ADODB.Command
Public feeCMD As ADODB.Command
Public userCMD As ADODB.Command
Public courseCMD As ADODB.Command
Public catCMD As ADODB.Command
Public SQLstr As String
Public auto As Boolean

Sub main()
frmLogin.Show
End Sub

Sub dbconnect()
Set libCON = New ADODB.Connection
libCON.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path &
"\Databases\lib_db.mdb;Persist Security Info=False"
End Sub

Mod menus
Option Explicit

Public Const bAmDebugging As Boolean = False


Public Type MenuDataInformation
ItemHeight As Integer
ItemWidth As Long
Icon As Long
HotKeyPos As Integer
Status As Byte
Caption As String
OriginalCaption As String
Parent As Long
ID As Long
End Type
Public Type PanelDataInformation
Height As Long
Width As Long
HKeyPos As Long
SideBar As Long
SideBarXY As Long
PanelIcon As Long
Status As Byte
Caption As String
FColor As Long
BColor As Long
SBarIcon As Long
ID As Long
End Type

26
Private Type MENUITEMINFO
cbSize As Long
fMask As Long
fType As Long
fState As Long
wID As Long
hSubMenu As Long
hbmpChecked As Long
hbmpUnchecked As Long
dwItemData As Long
dwTypeData As Long
cch As Long
End Type
Private Type MEASUREITEMSTRUCT
CtlType As Long
CtlID As Long
ItemId As Long
ItemWidth As Long
ItemHeight As Long
ItemData As Long
End Type
Private Type DRAWITEMSTRUCT
CtlType As Long
CtlID As Long
ItemId As Long
itemAction As Long
itemState As Long
hwndItem As Long
hDC As Long
rcItem As RECT
ItemData As Long
End Type
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
Private Type BITMAP
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
Private Type ICONINFO

27
fIcon As Long
xHotSpot As Long
yHotSpot As Long
hbmMask As Long
hbmColor As Long
End Type

' APIs needed to retrieve menu information


Private Declare Function WindowFromDC Lib "user32" (ByVal hDC As Long) As
Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long,
lpRect As RECT) As Long
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA"
(LpVersionInformation As OSVERSIONINFO) As Long
Private Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal
nPos As Long) As Long
Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long)
As Long
Private Declare Function GetMenuItemID Lib "user32" (ByVal hMenu As Long,
ByVal nPos As Long) As Long
Private Declare Function SetMenuItemInfo Lib "user32" Alias "SetMenuItemInfoA"
(ByVal hMenu As Long, ByVal un As Long, ByVal bool As Boolean,
lpcMenuItemInfo As MENUITEMINFO) As Long
Private Declare Function GetMenuItemInfo Lib "user32" Alias _
"GetMenuItemInfoA" (ByVal hMenu As Long, ByVal uItem As Long, _
ByVal byPosition As Long, lpMenuItemInfo As MENUITEMINFO) As Boolean
Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC
As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (pDest As Any, pSource As Any, ByVal ByteLen As Long)
Private Declare Function OffsetRect Lib "user32" (lpRect As RECT, ByVal x As
Long, ByVal y As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject
As Long, ByVal nCount As Long, lpObject As Any) As Long
Private Declare Function GetIconInfo Lib "user32" (ByVal hIcon As Long, piconinfo
As ICONINFO) As Long
Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long,
ByVal bRevert As Long) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal
dwBytes As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As
Long
' Subclassing APIs & stuff
Public Declare Function CallWindowProc Lib "user32" Alias _
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, ByVal MSG As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long

28
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Private Declare Function SetGraphicsMode Lib "gdi32" (ByVal hDC As Long,
ByVal iMode As Long) As Long
Private Declare Function IsZoomed Lib "user32" (ByVal hwnd As Long) As Long
' Subclassing & Windows Message Constants
Public Const GWL_WNDPROC = (-4)
Private Const WM_DRAWITEM = &H2B
Private Const WM_MEASUREITEM = &H2C
Private Const WM_INITMENU = &H116
Private Const WM_INITMENUPOPUP = &H117
Private Const WM_ENTERIDLE = &H121
Private Const WM_MDICREATE = &H220
Private Const WM_MDIACTIVATE = &H222
Private Const WM_ENTERMENULOOP = &H211
Private Const WM_EXITMENULOOP = &H212

Private Const GMEM_FIXED = &H0


Private Const GMEM_ZEROINIT = &H40
Private Const GPTR = (GMEM_FIXED Or GMEM_ZEROINIT)

' Menu Constants


Private Const MF_BYCOMMAND = &H0
Private Const MF_BYPOSITION = &H400
Private Const MF_OWNERDRAW = &H100
Private Const MF_SEPARATOR = &H800
Private Const MFT_SEPARATOR = MF_SEPARATOR
Private Const ODS_SELECTED = &H1
Private Const ODT_MENU = 1
Private Const MIIM_TYPE = &H10
Private Const MIIM_DATA = &H20
Private Const MIIM_SUBMENU = &H4

Private MenuData As Collection


Private ActiveHwnd As String
Private iTabOffset As Integer
Private lSubMenu As Long
Private lMDIchildClosed As Long
Private VisibleMenus As Collection

Public Sub SetMenus(Form_hWnd As Long, Optional MenuImageList As Control)


If bAmDebugging Then Exit Sub

Dim lMenus As Long, Looper As Integer


On Error Resume Next
If GetFormHandle(Form_hWnd) = -1 Then Exit Sub

lMenus = MenuData(CStr(Form_hWnd)).MainMenuID
If Err Then ' then new form to subclass

29
' Initialize a collection of classes if needed
If MenuData Is Nothing Then Set MenuData = New Collection
Dim NewMenuData As New clsMyMenu
' save the ImageList & Handle to the form's menu
With NewMenuData
.SetImageViewer MenuImageList
.MainMenuID = GetMenu(Form_hWnd)
' used to redirect MDI children to parent for submenu info (see
MsgProc:MDIactivate)
.ParentForm = Form_hWnd
End With
' Add the class to the class collection & remove the instance of the new class
MenuData.Add NewMenuData, CStr(Form_hWnd)
Set NewMenuData = Nothing
Else
' form is already subclassed, do nothing!
Exit Sub
End If
Err.clear
ActiveHwnd = CStr(Form_hWnd) ' set collection index to current form
CleanMDIchildMenus
lMenus = GetMenuItemCount(MenuData(ActiveHwnd).MainMenuID)
For Looper = 0 To lMenus - 1
'GetMenuMetrics GetSubMenu(MenuData(ActiveHwnd).MainMenuID, Looper)
Next
SetFreeWindow True ' hook the window so we can intercept windows
messages
End Sub

Public Sub ReleaseMenus(hwnd As Long)


'
=============================================================
========
' Sub prepares for Forms unloading
' This must be placed in the forms Unload event in order to
' release memory & prevent crash of program
'
=============================================================
========

If MenuData Is Nothing Then Exit Sub


On Error GoTo ByPassRelease
ActiveHwnd = CStr(hwnd) ' set current index
SetFreeWindow False ' unhook the window
On Error Resume Next
If MenuData(ActiveHwnd).ChildStatus = 1 Then
lMDIchildClosed = MenuData(ActiveHwnd).ParentForm
End If
' remove references to that form's class & ultimately unload the class
MenuData.Remove ActiveHwnd

30
If MenuData.Count = 0 Then
' here we clean up a little when all subclassed forms have been unloaded
Set MenuData = Nothing ' erase the collection of classes which will unload the
class
DestroyMenuFont ' get rid of memory font
modDrawing.TargethDC = 0 ' get rid of refrence in that module
End If
ByPassRelease:
End Sub

Private Sub CleanMDIchildMenus()


' reset parent's menu items (see that routine for remarks)
If lMDIchildClosed = 0 Then Exit Sub
Dim Looper As Long, mMenu As Long, mII As MENUITEMINFO
mII.cbSize = Len(mII)
mII.fMask = &H1 Or &H2
mII.fType = 0
On Error Resume Next
With MenuData(CStr(lMDIchildClosed))
For Looper = .PanelIDcount To 1 Step -1
mMenu = .GetPanelID(Looper)
If GetMenuItemCount(mMenu) < 0 Then .PurgeObsoleteMenus mMenu
Next
End With
lMDIchildClosed = 0
End Sub

Public Function MsgProc(ByVal hwnd As Long, ByVal wMsg As Long, _


ByVal wParam As Long, ByVal lParam As Long) As Long

'
=============================================================
========
' Here we determine which messages will be processed, relayed or
' skipped. Basically, we send anything thru unless we are measuring
' or drawing an item.
'
=============================================================
========

On Error GoTo SendMessageAsIs


' the following is a tell-tale sign of a system menu
If lParam = &H10000 Then Err.Raise 5
ActiveHwnd = CStr(hwnd) ' ensure index to current form is set
Select Case wMsg
Case WM_ENTERMENULOOP
'Debug.Print "entering loop"
' When a menu is activated, no changes can be made to the captions, enabled
status, etc
' So we will save each submenu as it is opened and read the info only once,

31
' this will prevent unnecessary reads each time the submenu is displayed
Set VisibleMenus = New Collection
Case WM_MDIACTIVATE
'Debug.Print "MDI child created"
' MDI children get their menus subclassed to the parent by Windows
' We set the class's parentform value to the MDI's parent & when
' submenus are processed, they are redirected to the parent
' The ChildStatus is set to clean out the parent's class when the
' child window is closed
' The GetSetMDIchildSysMenu command is run to store the system menu
' with the parent form. When the child is maximized its system menu
' shows up on the parent form & needs to be compared so the class
' doesn't draw for the system menu which it can't do!
MenuData(ActiveHwnd).ParentForm = GetParent(GetParent(hwnd))
MenuData(CStr(MenuData(ActiveHwnd).ParentForm)).GetSetMDIchildSysMen
u GetSystemMenu(hwnd, False), True
MenuData(ActiveHwnd).ChildStatus = 1
Case WM_MEASUREITEM
'Debug.Print "measuring"
' occurs after menu initialized & before drawing takes place
' send to drawing routine to measure the height/width of the menu panel
' If we measured it, don't let windows measure it again
If CustomDrawMenu(wMsg, lParam, wParam) = True Then Exit Function
Case WM_INITMENUPOPUP ', WM_INITMENU
If wParam = 0 Then Err.Raise 5 ' ignore these messages & pass them thru
'Debug.Print "Popup starts"
' Occurs each time a menu is about to be displayed, wMsg is the handle
' Send flag to drawing routine to allow icons to be redrawn
CustomDrawMenu wMsg, 0, 0
GetMenuMetrics wParam ' get measurements for menu items
' allow message to pass to the destintation
Case WM_DRAWITEM
'Debug.Print "drawing"
' sent numerous times, just about every time the mouse moves
' over the menu. Send flag to redraw menu if needed
' If we drew it, don't let windows redraw it
If CustomDrawMenu(wMsg, lParam, wParam) = True Then Exit Function
Case WM_EXITMENULOOP
'Debug.Print "exiting loop"
' When a menu is clicked on or closed, we remove the collection of submenus
' so they can be redrawn again as needed
Set VisibleMenus = Nothing
Case WM_ENTERIDLE
'Debug.Print "Popup ends"
' occurs after the entire menu has been measured & displayed
' at least once. Send flag to not redraw icons
CustomDrawMenu wMsg, 0, 0
End Select
SendMessageAsIs:

32
MsgProc = CallWindowProc(MenuData(ActiveHwnd).OldWinProc, hwnd, wMsg,
wParam, lParam)
End Function

Public Function GetMenuIconID(Menu_Caption As String) As Long


'
=============================================================
========
' Returns the icon assigned in the menu caption as a long value
' Example: {IMG:9}&Open would return 9
' Note: Not used in any modules here, but provided for programmer use
' if needed in their applications
'
=============================================================
========
Dim i As Integer
On Error GoTo NoIcon
i = InStr(Menu_Caption, "{IMG:")
If i Then
GetMenuIconID = Val(Mid$(Menu_Caption, InStr(Menu_Caption, ":") + 1))
End If
Exit Function
NoIcon:
GetMenuIconID = 0
End Function

Private Sub GetMenuMetrics(hSubMenu As Long)


'
=============================================================
========
' Routine gets the meaurements of the submenus & their submenus,
' their checked status, enabled status,
' control keys, icon index, etc
'
=============================================================
========

Dim lMenus As Long, hWndRedirect As String


Dim Looper As Long, meDC As Long, lmnuID As Long, sysMenuLoc As Long
Dim mII As MENUITEMINFO, mI() As Byte
Dim tRect As RECT, lMetrics(0 To 10) As Long
Dim sCaption As String, sBarCaption As String
Dim sHotKey As String, bTabOffset As Boolean
Dim IconID As Integer, iTransparency As Integer
Dim bSetHotKeyOffset As Boolean, bNewItem As Boolean
Dim bHasIcon As Boolean, bRecalcSideBar As Long
Dim iSeparator As Integer, bSpecialSeparator As Boolean

On Error Resume Next

33
If MenuData(ActiveHwnd).GetSetMDIchildSysMenu(hSubMenu, False) = True Then
Exit Sub
If Not VisibleMenus Is Nothing Then
' here we track which submenus are currently visible so we don't
' re-process data which isn't needed until after the submenu is closed
lMenus = VisibleMenus(CStr(hSubMenu))
If lMenus Then Exit Sub
End If
On Error GoTo 0
meDC = GetDC(CLng(ActiveHwnd))
hWndRedirect = MenuData(ActiveHwnd).ParentForm
' Get the ID for the next submenu item
lMenus = GetMenuItemCount(hSubMenu)
lSubMenu = hSubMenu
modDrawing.TargethDC = meDC
DetermineOS
With MenuData(hWndRedirect) ' class for this form
For Looper = 0 To lMenus - 1 ' loop thru each subitem
' get the submenu item
bSpecialSeparator = False
iSeparator = 0: iTransparency = 0
sHotKey = ""
' now set some flags & stuff to return the caption, checked & enabled status
' by referencing the dwTypeData as a byte array vs long or string,
' we bypass the VB crash that happens on Win98 & XP & probably others
ReDim mI(0 To 255)
mII.cbSize = Len(mII)
mII.fMask = &H10 Or &H1 Or &H2
mII.fType = 0
mII.dwTypeData = VarPtr(mI(0))
mII.cch = UBound(mI)
' get the submenu item information
GetMenuItemInfo hSubMenu, Looper, True, mII
'Debug.Print lmnuID; "has submenus"; mII.hSubMenu
If Abs(mII.wID) = 4096 Or mII.wID = -1 Then Exit Sub
lmnuID = mII.wID
bNewItem = .SetMenuID(lmnuID, hSubMenu, False, True)
sCaption = Left$(StrConv(mI, vbUnicode), mII.cch)
If Len(Replace$(sCaption, Chr$(0), "")) = 0 Then sCaption = .OriginalCaption
If Left(UCase(sCaption), 9) = "{SIDEBAR:" Then sBarCaption = sCaption
'Debug.Print hWndRedirect; hSubMenu; lmnuID; " Caption: "; sCaption
If .OriginalCaption = sCaption And bNewItem = False Then
' here we can get cached info vs reprocessing it again
lMetrics(1) = lMetrics(1) + .ItemHeight
lMetrics(10) = .ItemWidth
If LoWord(lMetrics(10)) > lMetrics(0) Then lMetrics(0) =
LoWord(lMetrics(10))
If HiWord(lMetrics(10)) > lMetrics(9) Then lMetrics(9) =
HiWord(lMetrics(10))
lMetrics(4) = .SideBarWidth

34
If .Icon <> 0 Then bHasIcon = True
If InStr(sCaption, Chr$(9)) Then bTabOffset = True
'Debug.Print "reading existing " & Looper + 1, sCaption
Else
bNewItem = True
If Len(sBarCaption) > 0 And bRecalcSideBar = 0 Then bRecalcSideBar =
lmnuID
.OriginalCaption = sCaption
.Status = 0
' new item or change in caption, let's get some measurements
' first extract the caption, controlkeys & icon
If InStr(sCaption, Chr$(9)) Then bTabOffset = True
' when Win98 encounters a hotkey above, it automatically
' increases the menu panel width. We need to note that
' so we can decrease the panel widh appropriately and
' offset the automatic increase. This helps prevent extra
' wide menu panels
If Left(UCase(sCaption), 9) = "{SIDEBAR:" Then
iSeparator = 1
.Status = .Status Or 16
.ItemHeight = 0
.ItemWidth = 0
.Icon = 0
Else
'Debug.Print "Caption "; sCaption
FindImageAndHotKey hWndRedirect, sCaption, iTransparency, sHotKey,
IconID
Debug.Print "iconid="; IconID
' identify whether or not this is a separator
iSeparator = Abs(CInt(Len(sCaption) = 0 Or Left$(sCaption, 1) = "-"))
If iSeparator = 0 Then iSeparator = Abs(CInt(mII.fType And
MF_SEPARATOR) = MF_SEPARATOR)
If iSeparator Then IconID = 0 ' no pictures on separator bars!
If Len(sCaption) > 0 And iSeparator = 1 Then
' separator bar with text
' calculate entire caption & set a few flags
sCaption = Mid$(sCaption, 2) & " " & sHotKey
bSpecialSeparator = True
sHotKey = "" ' not used for separators
End If
' start saving the information
.Caption = Trim$(sCaption & " " & sHotKey)
.Icon = IconID
.Status = .Status Or iTransparency * 4
.Status = .Status Or iSeparator * 2
If IconID Then bHasIcon = True
SetMenuFont True, , bSpecialSeparator ' add smaller menu font
' measure the caption width to help identify how wide
' the menu panel should be (greatest width of all submenu items)

35
DrawText meDC, sCaption, Len(sCaption), tRect, DT_CALCRECT Or
DT_LEFT Or DT_SINGLELINE Or DT_NOCLIP
' keep track of the largest width, this will be used to
' left align control keys for the entire panel
If tRect.Right > lMetrics(0) Then lMetrics(0) = tRect.Right
lMetrics(10) = tRect.Right
If iSeparator = 0 Or bSpecialSeparator = True Then
' set min height text menu items to match 16x16 icon height
If tRect.Bottom < 10 And bSpecialSeparator = False Then tRect.Bottom
= 10
tRect.Bottom = tRect.Bottom + 6
Else
tRect.Bottom = 5 ' make default separators 0 height
End If
' store the height of the caption text
.ItemHeight = tRect.Bottom
lMetrics(1) = lMetrics(1) + tRect.Bottom
SetMenuFont False
If Len(sHotKey) Then
.HotKeyPos = Len(sCaption) + 1
' now do the same for the hotkey
DrawText meDC, Trim(sHotKey), Len(Trim(sHotKey)), tRect,
DT_CALCRECT Or DT_LEFT Or DT_NOCLIP Or DT_SINGLELINE
' keep track of the widest control key text
' this is used w/widest caption to determine overall
' panel width including icons & checkmarks. Add 12 pixels for
' buffer between end of caption & beginning of control key
If tRect.Right > lMetrics(9) Then lMetrics(9) = tRect.Right
.ItemWidth = MakeLong(CInt(lMetrics(10)), CInt(tRect.Right))
Else
.ItemWidth = MakeLong(CInt(lMetrics(10)), 0)
End If
End If
End If
' we ensure the item is drawn by us
' force a separator status if appropriate
mII.fMask = 0
If mII.fType = MF_SEPARATOR Or iSeparator = 1 Then
mII.fType = MF_SEPARATOR Or MF_OWNERDRAW
Else ' otherwise it's normal
mII.fType = mII.fType Or MF_OWNERDRAW
End If
mII.fMask = mII.fMask Or MIIM_TYPE Or MIIM_DATA ' reset mask
' save updates to allow us to draw the menu item
SetMenuItemInfo hSubMenu, Looper, True, mII
Next
If Looper > 0 Then ' menu items processed
If bRecalcSideBar = 0 Then ' sidebar menu id
' if no sidebar was processed, then check the overall panel height
' if it changed, we need to reprocess the sidebar again since

36
' the graphics & text are centered in the panel
If .PanelHeight <> lMetrics(1) And .SideBarItem <> 0 Then bRecalcSideBar
= lmnuID
End If
lMetrics(3) = 5 + Abs(CInt(bHasIcon)) * 18
lMetrics(2) = lMetrics(0) + 12
lMetrics(0) = lMetrics(2) + lMetrics(9) + lMetrics(3) + lMetrics(4) +
CInt(bTabOffset) * iTabOffset
If bRecalcSideBar Then
.SetMenuID bRecalcSideBar, hSubMenu, False, False
ReturnSideBarInfo hWndRedirect, sBarCaption, lMetrics(), meDC
End If
.UpdatePanelID lMetrics(), sBarCaption, (bRecalcSideBar = 0)
End If
End With
If Not VisibleMenus Is Nothing Then VisibleMenus.Add 1, (CStr(hSubMenu))
' now we replace the default font & release the form's DC
SetMenuFont False, meDC
ReleaseDC CLng(ActiveHwnd), meDC
Erase lMetrics
Erase mI
End Sub

Private Sub FindImageAndHotKey(hWndRedirect As String, sKey As String,


imgTransparency As Integer, sAccel As String, imgIndex As Integer)
'
=============================================================
========
' This routine extracts the imagelist refrence and resets it if the
' image doesn't exist or not imagelist was provided
'
=============================================================
========
On Error Resume Next
Dim i As Integer, sSpecial As String, sHeader As String
imgIndex = 0
imgTransparency = 0
If Left$(UCase(sKey), 5) = "{IMG:" Then
i = InStr(sKey, "}")
If i Then
sHeader = UCase(Left$(sKey, i))
sKey = Mid$(sKey, i + 1)
' extract the image index
imgIndex = Val(Mid$(sHeader, 6))
' if the value<1 or >nr of images, then reset it to zero
Debug.Print "icon count="; MenuData(hWndRedirect).TotalIcons
If imgIndex < 1 Or imgIndex > MenuData(hWndRedirect).TotalIcons Then
imgIndex = 0
Else ' optional transparency flag
' Y=always use transparency

37
' N=never user transparency
' default: Icons never use transparency, Bitmaps always
If InStr(sHeader, "|Y}") Then imgTransparency = 1
If InStr(sHeader, "|N}") Then imgTransparency = 2
End If
End If
End If
' Parse the Caption & the Control Key
sAccel = ""
' First let's see if it's a menu builder supplied control key
' if so, it's easy to identify 'cause it is preceeded by a vbTab
i = InStr(sKey, Chr$(9))
If i Then ' yep, menu builder supplied control key
sAccel = Trim$(Mid$(sKey, i + 1))
sKey = Trim$(Left$(sKey, i - 1))
Else
' user supplied control key, a little more difficult to find
For i = 1 To 3 ' look for Ctrl, Alt & Shift combinations 1st
If InStr(UCase(sKey), Choose(i, "CTRL+", "SHIFT+", "ALT+")) Then
' if found, then exit routine
sAccel = Trim$(Mid$(sKey, InStr(UCase(sKey), Choose(i, "CTRL+",
"SHIFT+", "ALT+"))))
sKey = Trim$(Left$(sKey, InStr(UCase(sKey), Choose(i, "CTRL+",
"SHIFT+", "ALT+")) - 1))
Exit Sub
End If
Next
For i = 1 To 15 ' look for F keys next
If Right$(UCase(sKey), Len("F" & i)) = "F" & i Then
' if found, then exit routine
sAccel = Trim$(Mid$(sKey, InStrRev(UCase(sKey), "F" & i)))
sKey = Trim$(Left$(sKey, InStrRev(UCase(sKey), UCase(sAccel)) - 1))
Exit Sub
End If
Next
' here we look for other types of hot keys, these can be customized
' as needed by following the logic below
For i = 1 To 6
' hot key looking for, it will be preceded by a space and must
' be at end of caption, otherwise we ignore it
sSpecial = Choose(i, " DEL", " INS", " HOME", " END", " PGUP", " PGDN")
If Right$(UCase(sKey), Len(sSpecial)) = sSpecial Then
sAccel = Trim$(Mid$(sKey, InStrRev(UCase(sKey), sSpecial)))
sKey = Trim$(Left$(sKey, InStrRev(UCase(sKey), sSpecial) - 1))
Exit For
End If
Next
End If
End Sub

38
Private Sub ReturnSideBarInfo(hWndRedirect As String, sBarInfo As String,
vBarInfo() As Long, tDC As Long)
'
=============================================================
==========
' This routine returns the sidebar information for the current submenu
' Basically we are parsing out the SIDEBAR caption
'
=============================================================
==========

Dim i As Integer, sImgID As String


Dim lRatio As Single, sText As String
Dim bMetrics As Boolean, sTmp As String
Dim lFont As Long, lFontM As LOGFONT, hPrevFont As Long
Dim tRect As RECT
Dim imgInfo As BITMAP, picInfo As ICONINFO
Dim TempBMP As Long, ImageDC As Long, sbarType As Integer

' here we are just adding a delimeter at end of string to make parsing easier
If Right$(sBarInfo, 1) = "}" Then sBarInfo = Left$(sBarInfo, Len(sBarInfo) - 1)
sBarInfo = sBarInfo & "|"
' stripoff the SIDEBAR header
i = InStr(UCase(sBarInfo), "{SIDEBAR:")
sBarInfo = Mid$(sBarInfo, InStr(sBarInfo, ":") + 1)
' return the type of sidebar Image or Text
i = InStr(sBarInfo, "|")
' if the next line <> TEXT then we have an image handle or image control
sImgID = Left$(sBarInfo, i - 1)

On Error Resume Next


' can't leave memory fonts running around loose -- wasted memory
If MenuData(hWndRedirect).SideBarIsText = True And
MenuData(hWndRedirect).SideBarItem <> 0 Then
' kill the previous font for this item, if any
DeleteObject MenuData(hWndRedirect).SideBarItem
End If
vBarInfo(10) = 0 ' reset to force no sidebar
' use with caution. Making width too small or too large
' may prevent menu from displaying or crash on memory
' suggest using between 32 & 64
If InStr(UCase(sBarInfo), "|WIDTH:") Then ' width of the sidebar (user-provided)
' undocumented! this allows the sidebar width to be modified
vBarInfo(4) = Val(Mid$(sBarInfo, InStr(UCase(sBarInfo), "|WIDTH:") + 7))
Else
' however, 32 pixels wide seems to look the best
vBarInfo(4) = 32 ' default width of sidebars
End If
If IsNumeric(sImgID) Then ' user is providing image handle vs a form picture
object

39
vBarInfo(10) = Val(sImgID) ' ref to picture if it exists
sbarType = 2 ' status: image sidebar
vBarInfo(9) = 8 ' type default as bmp
Else
If sImgID = "TEXT" Then
sbarType = 4 ' status: text sidebar
vBarInfo(9) = 0
If InStr(UCase(sBarInfo), "|CAPTION:") Then
sText = Mid$(sBarInfo, InStr(UCase(sBarInfo), "|CAPTION:") + 9)
i = InStr(sText, "|")
sText = Left$(sText, i - 1)
End If
sBarInfo = UCase(sBarInfo) ' make it easier to parse
If InStr(sBarInfo, "|FONT:") Then
' parse out the font
sTmp = Mid$(sBarInfo, InStr(sBarInfo, "|FONT:") + 6)
i = InStr(sTmp, "|")
sTmp = Left$(sTmp, i - 1)
Else
sTmp = "Arial" ' default if not provided
End If
lFontM.lfCharSet = 0 ' scalable only
lFontM.lfFaceName = sTmp
' if user wants other font attributes, then make it so
If InStr(sBarInfo, "|BOLD") Then sTmp = sTmp & " Bold"
If InStr(sBarInfo, "|ITALIC") Then sTmp = sTmp & " Italic"
lFontM.lfFaceName = sTmp & Chr$(0)
If InStr(sBarInfo, "|UNDERLINE") Then lFontM.lfUnderline = 1
' if user wants a different fontsize then make it so
If InStr(sBarInfo, "|FSIZE:") Then
i = Val(Mid$(sBarInfo, InStr(sBarInfo, "|FSIZE:") + 7))
If i < 4 Then i = 12 ' min & max fonts
If i > 24 Then i = 24
Else
i = 12 ' default font size
End If
Do
' here we are going to create fonts to see if it will
' fit in the sidebar, unfortunately we need to do this
' each time the menubar is initially displayed or resized because
' the sidebar height may have changed with adding/removing
' or making menu items invisible
lFontM.lfHeight = (i * -20) / Screen.TwipsPerPixelY
' can't rotate the font before measuring it - per MSDN drawtext won't measure
rotated fonts
lFont = CreateFontIndirect(lFontM) ' create the font without rotation
hPrevFont = SelectObject(tDC, lFont) ' load it into the DC
' see if it will fit in the sidebar
DrawText tDC, sText, Len(sText), tRect, DT_CALCRECT Or DT_LEFT Or
DT_SINGLELINE Or DT_NOCLIP Or &H800

40
' regardless we delete the font, cause we'll need to rotate it
SelectObject tDC, hPrevFont
DeleteObject lFont
If tRect.Right > vBarInfo(1) Or tRect.Bottom > vBarInfo(4) Then
' font is too big, reduce it by 1 and try again
i=i-1
If i < 4 Then Exit Do
Else ' font is ok, now we rotate it & save it
lFontM.lfEscapement = 900
lFont = CreateFontIndirect(lFontM) ' create the font
vBarInfo(10) = lFont ' save it
vBarInfo(8) = tRect.Right ' measurements
vBarInfo(5) = tRect.Bottom
Exit Do
End If
Loop
Else
' here we have an image/picturebox control containing an image
' we need to extract the image handle
Dim formID As Long, vControl As Control, bIsMDI As Boolean
' loop thru each open form to determine which is the active
formID = GetFormHandle(CLng(hWndRedirect), bIsMDI)
If formID > -1 Then
sbarType = 2 'status: image sidebar
' let's see if the control passed is indexed
If Right$(sImgID, 1) = ")" Then ' indexed image
i = InStrRev(sImgID, "(")
sTmp = Left$(sImgID, i - 1)
i = Val(Mid$(sImgID, i + 1))
If bIsMDI Then
If Forms(formID).ActiveForm Is Nothing Then
Set vControl = Forms(formID).Controls(sTmp).Item(i)
Else
' when control is in an MDIs active form, we reference it this way
Set vControl = Forms(formID).ActiveForm.Controls(sTmp).Item(i)
End If
Else
Set vControl = Forms(formID).Controls(sTmp).Item(i)
End If
Else
If bIsMDI Then
If Forms(formID).ActiveForm Is Nothing Then
Set vControl = Forms(formID).Controls(sImgID)
Else
' when control is in an MDIs active form, we reference it this way
Set vControl = Forms(formID).ActiveForm.Controls(sImgID)
End If
Else
Set vControl = Forms(formID).Controls(sImgID)
End If

41
End If
' cache the picture handle & type
vBarInfo(10) = vControl.Picture.Handle
If vControl.Picture.Type = 3 Then vBarInfo(9) = 16 Else vBarInfo(9) = 8
Set vControl = Nothing
End If
End If
End If
If vBarInfo(10) = 0 Then
'failed retrieving sidebar information
Debug.Print "Sidebar failed"
vBarInfo(4) = 0
Exit Sub
End If
sBarInfo = UCase(sBarInfo) ' make it easier to parse
'ok, let's get the rest of the attributes
If InStr(sBarInfo, "|BCOLOR:") Then
' Background color for the sidebar
Select Case Left$(Mid$(sBarInfo, InStr(sBarInfo, "|BCOLOR:") + 8), 4)
Case "NONE": vBarInfo(6) = -1
Case "BACK": ' short for background
' if a text sidebar & background was provided we change to default
If sbarType = 2 Then vBarInfo(6) = -2 Else vBarInfo(6) = -1
Case Else ' numeric background color -- use it
vBarInfo(6) = Val(Mid$(sBarInfo, InStr(sBarInfo, "|BCOLOR:") + 8))
End Select
Else
vBarInfo(6) = -1 ' default: use the menubar background color
End If
If vBarInfo(6) = -1 Then vBarInfo(6) = GetSysColor(COLOR_MENU)
If vBarInfo(10) Then
If sbarType = 2 Then
' now if an image sidebar, we call subroutine for more attributes
GoSub DrawPicture
' let's get the size of the image vs the size of the menu panel &
' either center or shrink the image to fit
' we will return the left offset, top offset & new image width, height
If vBarInfo(5) > vBarInfo(4) Or vBarInfo(8) > vBarInfo(1) Then ' image is
larger than menu panel
If vBarInfo(5) / vBarInfo(4) > vBarInfo(8) / vBarInfo(1) Then
lRatio = vBarInfo(4) / vBarInfo(5)
Else
lRatio = vBarInfo(1) / vBarInfo(8)
End If
vBarInfo(5) = CInt(vBarInfo(5) * lRatio)
vBarInfo(8) = CInt(vBarInfo(8) * lRatio)
End If
vBarInfo(7) = MakeLong(CInt(vBarInfo(5)), CInt(vBarInfo(8)))
' save the left & top offsets for the image, this way we don't have
' to remeasure when the menu is being displayed.

42
vBarInfo(5) = MakeLong((vBarInfo(4) - vBarInfo(5)) \ 2, (vBarInfo(1) -
vBarInfo(8)) \ 2)
Else
' if user want's gradient background for text sidebar then
If InStr(sBarInfo, "|GRADIENT") > 0 And sbarType = 4 Then vBarInfo(9) =
vBarInfo(9) Or 32
' text sidebar, let's get the forecolor of the text & black is default
If InStr(sBarInfo, "|FCOLOR:") Then
vBarInfo(7) = Val(Mid$(sBarInfo, InStr(sBarInfo, "|FCOLOR:") + 8))
If vBarInfo(7) < 0 Then vBarInfo(7) = 0
Else
vBarInfo(7) = 0
End If
vBarInfo(5) = MakeLong(CInt(vBarInfo(5)), CInt(vBarInfo(8)))
End If
End If
vBarInfo(9) = sbarType Or vBarInfo(9)
vBarInfo(0) = vBarInfo(0) + vBarInfo(4)
'Debug.Print "font?"; (vBarInfo(9) And 4) = 4; vBarInfo(10)
sBarInfo = sText
Exit Sub

DrawPicture:
' this routine is used when....
' 1. When we need the background color for a mask
' 2. Image passed is a control to get height/width values
'Get the info about our image
If GetObject(vBarInfo(10), Len(imgInfo), imgInfo) = 0 Then 'And vControl Is
Nothing Then
GetIconInfo vBarInfo(10), picInfo
If picInfo.xHotSpot = 0 Or picInfo.yHotSpot = 0 Then
'if the image passed was a handle vs control and not a bitmap
' sidebar fails
Debug.Print "Sidebar failed image is not a bitmap or icon type"
vBarInfo(10) = 0
vBarInfo(4) = 0
Return
End If
vBarInfo(9) = 16
vBarInfo(5) = picInfo.xHotSpot
vBarInfo(8) = picInfo.yHotSpot
Else
vBarInfo(9) = 8
vBarInfo(5) = imgInfo.bmWidth
vBarInfo(8) = imgInfo.bmHeight
End If
Err.clear
If vBarInfo(6) = -2 Then
Dim picIcon As PictureBox
Forms(formID).Controls.Add "VB.PictureBox", "pic___Ic_on_s", Forms(formID)

43
With Forms(formID).Controls("pic___Ic_on_s")
.Visible = False
.AutoRedraw = True
If vBarInfo(6) = -2 Then
If vBarInfo(9) = 8 Then i = 4 Else i = 3
' draw the image to the picturebox
If DrawState(.hDC, 0, 0, vBarInfo(10), 0, 0, 0, 0, 0, CLng(i)) = 0 Then
' drawing failed, try again with differnt picture type
If i = 4 Then i = 3 Else i = 4
DrawState .hDC, 0, 0, vBarInfo(10), 0, 0, 0, 0, 0, CLng(i)
End If
' get the mask color
vBarInfo(6) = GetPixel(.hDC, 0, 0)
End If
End With
Forms(formID).Controls.Remove "pic___Ic_on_s"
End If
Return
End Sub

Private Sub SetFreeWindow(bSet As Boolean)


'
=============================================================
========
' This routine hooks or unhooks a window & is used when
' menus are first set and when a form closes
'
=============================================================
========

If MenuData(ActiveHwnd).OldWinProc = 0 And bSet = True Then


' hook only if window not already hooked
MenuData(ActiveHwnd).OldWinProc = SetWindowLong(CLng(ActiveHwnd),
GWL_WNDPROC, AddressOf MsgProc)
Else
If MenuData(ActiveHwnd).OldWinProc <> 0 And bSet = False Then
' hook only if window was already hooked
SetWindowLong CLng(ActiveHwnd), GWL_WNDPROC,
MenuData(ActiveHwnd).OldWinProc
MenuData(ActiveHwnd).OldWinProc = 0
End If
End If
End Sub

Private Function CustomDrawMenu(wMsg As Long, lParam As Long, wParam As


Long) As Boolean
'
=============================================================
========
' Here we simply measure & draw menu items based on settings saved

44
' in the form's related class
'
=============================================================
========

Dim IsSep As Boolean, hWndRedirect As String


Static bDrawIcon As Boolean, bDrawPanel As Boolean, bGetPanelData As Boolean
Static lOffsets(0 To 2) As Long, lLastSubMenu As Long
' MDI children menus are subclassed to parent by Windows
' However, if the child isn't maximized in the MDI parent, then the menus are
' not subclassed (pain in the neck until this was figured out & re-thought)
' To work around this & prevent the submenus from being stored in both the parent
' and child classes, I redirect the actions to the parent via the GetMenuMetrics sub
' regardless whether or not the child is maximized
' Since each menu drawn is now stored the parent class, we redirect to the routine to
' get the info from the parent. If the form is the MDI parent or is a non-MDI form,
' then the ParentForm property is the same as the form's actual handle
hWndRedirect = MenuData(ActiveHwnd).ParentForm ' here we set this flag.

Select Case wMsg


Case WM_INITMENUPOPUP
' menu is about to be displayed, set flag to allow drawing of icons
bDrawIcon = True: bDrawPanel = True: bGetPanelData = True
lLastSubMenu = 0
Case WM_DRAWITEM
Dim DrawInfo As DRAWITEMSTRUCT
Dim IsSideBar As Boolean
Dim hBR As Long, hOldBr As Long, hChkBr As Long
Dim hPen As Long, hOldPen As Long, lTextColor As Long
Dim tRect As RECT
Dim iRectOffset As Integer, iSBoffset As Integer
Dim sAccelKey As String, sCaption As String
Dim bMenuItemDisabled As Boolean, bMenuItemChecked As Boolean
Dim bSelected As Boolean, bHasIcon As Boolean

'Get DRAWINFOSTRUCT which gives us sizes & indexes


Call CopyMemory(DrawInfo, ByVal lParam, LenB(DrawInfo))
' only process menu items, other windows items send above message
' and we don't want to interfere with those. Also if we didn't
' process it, we don't touch it
lSubMenu = DrawInfo.hwndItem
If MenuData(hWndRedirect).SetMenuID(DrawInfo.ItemId, DrawInfo.hwndItem,
False, False) = False Then Exit Function
If DrawInfo.CtlType <> ODT_MENU Then Exit Function
CustomDrawMenu = True
IsSideBar = CBool((MenuData(hWndRedirect).Status And 16) = 16)
If (IsSideBar = True And bDrawPanel = False) Then Exit Function
IsSep = (MenuData(hWndRedirect).Status And 2) = 2 And IsSideBar = False
' get the checked & enabled status

45
bMenuItemDisabled = CBool((DrawInfo.itemState And 6) = 6 Or
(DrawInfo.itemState And 7) = 7)
' don't continue the process if the disabled item or separator
' was already drawn, no need to redraw it again - it doesn't change
If bDrawIcon = False And (bMenuItemDisabled = True Or IsSep = True) Then Exit
Function
bMenuItemChecked = CBool((DrawInfo.itemState And 8) = 8 Or
(DrawInfo.itemState And 9) = 9)
' set a reference in the drawing module to this menu's DC & set the font
modDrawing.TargethDC = DrawInfo.hDC
If bDrawPanel = True Or lLastSubMenu <> DrawInfo.hwndItem Then
Dim pData(0 To 10) As Long
MenuData(hWndRedirect).GetPanelInformation pData(), sCaption
lOffsets(2) = pData(3)
If lOffsets(2) Then lOffsets(2) = lOffsets(2) + 5
lOffsets(1) = pData(4)
If pData(4) Then lOffsets(1) = lOffsets(1) + 3
lOffsets(0) = lOffsets(1) + lOffsets(2)
If bDrawPanel = True Then
If pData(10) <> 0 Then
Debug.Print "panel xy:"; pData(4), pData(1)
tRect.Bottom = pData(1)
tRect.Right = pData(4)
hBR = CreateSolidBrush(pData(6))
hPen = GetPen(1, pData(6))
hOldPen = SelectObject(DrawInfo.hDC, hPen)
hOldBr = SelectObject(DrawInfo.hDC, hBR)
DrawRect 0, 0, tRect.Right, tRect.Bottom
SelectObject DrawInfo.hDC, hOldBr
DeleteObject hBR
SelectObject DrawInfo.hDC, hOldPen
DeleteObject hPen
pData(8) = CLng(HiWord(pData(5)))
pData(5) = CLng(LoWord(pData(5)))
If (pData(9) And 2) = 2 Then
modDrawing.TargethDC = DrawInfo.hDC
DrawMenuIcon pData(10), Abs(CInt((pData(9) Or 16) = 16) * 2) + 1, _
tRect, False, , 2, CInt(pData(5)), CInt(pData(8)), LoWord(pData(7)),
HiWord(pData(7)), pData(6)
Else
SetBkMode DrawInfo.hDC, NEWTRANSPARENT
DetermineOS DrawInfo.hDC
If (pData(9) And 32) = 32 Then DoGradientBkg pData(6), tRect,
CLng(hWndRedirect)
SetMenuFont True, , , pData(10)
tRect.Left = (pData(4) - pData(5)) \ 2
tRect.Top = (pData(1) - pData(8)) \ 2 + pData(8)
SetTextColor DrawInfo.hDC, pData(7)
DrawText DrawInfo.hDC, sCaption, Len(sCaption), tRect, DT_LEFT Or
DT_NOCLIP Or DT_SINGLELINE Or &H800

46
SetMenuFont False
End If
End If
End If
bDrawPanel = False
lLastSubMenu = DrawInfo.hwndItem
Erase pData
End If
If IsSideBar Then
CustomDrawMenu = True
Exit Function
End If
SetMenuFont True
' determine if this item is focused or not which also determines
' what colors we use when we are drawing
bSelected = (DrawInfo.itemState And ODS_SELECTED) = ODS_SELECTED
' Now let's set some colors to draw with
With DrawInfo
If bSelected = True And bMenuItemDisabled = False And IsSep = False Then
hBR = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT))
hPen = GetPen(1, GetSysColor(COLOR_HIGHLIGHT))
lTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT)
Else
hBR = CreateSolidBrush(GetSysColor(COLOR_MENU))
hPen = GetPen(1, GetSysColor(COLOR_MENU))
If bMenuItemDisabled Or IsSep = True Then
lTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT)
Else
lTextColor = GetSysColor(COLOR_MENUTEXT)
End If
End If
If bMenuItemDisabled = True Then
' for checked & disabled items, we use default back color
hChkBr = CreateSolidBrush(GetSysColor(COLOR_MENU))
Else
' here we set the back color of a depressed button
hChkBr = CreateSolidBrush(GetSysColor(COLOR_BTNLIGHT))
End If
'Select our new, correctly colored objects:
hOldBr = SelectObject(.hDC, hBR)
hOldPen = SelectObject(.hDC, hPen)
'Do we have a separator bar?
bHasIcon = False
sCaption = MenuData(hWndRedirect).Caption
If Not IsSep Then
' Ok, does this item have an icon?
' Here we do one more extra check in case the ImageViewer
' is no longer available or has no images (then handle is 0)
' we also set the offset for highlighting rectangle's left
' edge so it doesn't highlight icons

47
If MenuData(hWndRedirect).ImageViewer > 0 And _
MenuData(hWndRedirect).Icon > 0 Then
bHasIcon = True
iRectOffset = lOffsets(0) - 2
Else
'If bMenuItemChecked Then
' iRectOffset = lOffsets(0) - 2
'Else
iRectOffset = lOffsets(1)
'End If
End If
'Draw the highlighting rectangle
DrawRect .rcItem.Left + iRectOffset, .rcItem.Top, .rcItem.Right,
.rcItem.Bottom
'Print the menu item's text
If MenuData(hWndRedirect).HotKeyPos Then
' we have a control key, so identify it & its left edge
sAccelKey = Mid$(sCaption, MenuData(hWndRedirect).HotKeyPos)
sCaption = Left$(sCaption, InStr(sCaption, sAccelKey))
End If
' send the caption, control key, icon offset, etc to be printed
tRect = .rcItem
DrawCaption .rcItem.Left + lOffsets(0), .rcItem.Top + 3, _
tRect, sCaption, sAccelKey, MenuData(hWndRedirect).HotKeyEdge,
lTextColor
If bMenuItemDisabled Then ' add the engraved affect
tRect = .rcItem ' get starting rectangle &
OffsetRect tRect, -1, -1 ' offset by 1 top & left
' print text again with offsets
DrawCaption .rcItem.Left + lOffsets(0) - 1, .rcItem.Top + 2, _
tRect, sCaption, sAccelKey, MenuData(hWndRedirect).HotKeyEdge, _
GetSysColor(COLOR_GRAYTEXT)
End If
If bMenuItemChecked Then
' for checked items, since they can have icons, we do a few
' things different. We make the checked item appear in a sunken
' box and make the backcolor of the box lighter than normal
SelectObject .hDC, hChkBr
DrawRect lOffsets(1), .rcItem.Top, lOffsets(0) - 5, .rcItem.Bottom - 1
ThreeDbox lOffsets(1) - 2, .rcItem.Top, lOffsets(0) - 3, .rcItem.Bottom - 2,
True, True
If bHasIcon = False Then
' now if the checked item doesn't have an icon we draw a checkmark in
the icons' place
DrawCheckMark .rcItem, IIf(bMenuItemDisabled, lTextColor,
GetSysColor(COLOR_MENUTEXT)), False, lOffsets(1)
If bMenuItemDisabled Then DrawCheckMark .rcItem,
GetSysColor(COLOR_GRAYTEXT), bMenuItemDisabled, lOffsets(1)
End If
End If

48
End If
'If the item has an icon, selected or not, disabled or not
If bHasIcon = True Then
If bDrawIcon = True Or bMenuItemChecked = True Then ' we are redrawing
icons
' extract icon handle, type & transparency option
Dim vIconDat() As Long
MenuData(hWndRedirect).GetIconData vIconDat(),
MenuData(hWndRedirect).Icon
'set up the location to be drawn
tRect.Left = 4 + lOffsets(1)
tRect.Top = ((.rcItem.Bottom - .rcItem.Top) - 16) \ 2 + .rcItem.Top
tRect.Right = tRect.Left + 16
tRect.Bottom = tRect.Top + 16
'send the icon information to be drawn
DrawMenuIcon vIconDat(0), vIconDat(1), tRect, bMenuItemDisabled,
True, vIconDat(2)
End If
SelectObject .hDC, hBR
If bMenuItemDisabled = False And bMenuItemChecked = False Then
' here we draw or remove the 3D box around the icon
ThreeDbox lOffsets(1), .rcItem.Top, lOffsets(0) - 5, .rcItem.Bottom - 1,
bSelected
End If
End If
If IsSep Then
'Finally, draw the special separator bar if needed
' however, if the separator has text, then we need to do
' some additional calculations
If Len(sCaption) Then
' separator bars with text
SetMenuFont True, , True ' use smaller font
tRect = .rcItem ' copy the menuitem coords
' send caption to be printed in menu-select color
' of course any color can be used & if you want to use the
' standard 3D gray disabled color then Rem out the next line
' and un-rem the next 3 lines & the second DrawCapton line
DrawCaption .rcItem.Left, .rcItem.Top + 3, tRect, sCaption, "", 0,
GetSysColor(COLOR_HIGHLIGHT), True, CInt(lOffsets(1))
'DrawCaption .rcItem.Left, .rcItem.Top + 3, tRect, sCaption, "", 0,
lTextColor, True
'tRect = .rcItem ' recopy menuitem coords
'OffsetRect tRect, -1, -1 ' move coords up & left by 1
' send caption again in gray
'DrawCaption .rcItem.Left - 1, .rcItem.Top + 2, tRect, sCaption, "", 0,
GetSysColor(COLOR_GRAYTEXT), True
If bMenuItemChecked = False Then
' here we add the lines on both sides of the separator caption
ThreeDbox 4 + lOffsets(1), _
(.rcItem.Bottom - .rcItem.Top) \ 2 + .rcItem.Top, _

49
tRect.Left - 4, _
(.rcItem.Bottom - .rcItem.Top) \ 2 + 1 + .rcItem.Top, True
ThreeDbox tRect.Right + 4, _
(.rcItem.Bottom - .rcItem.Top) \ 2 + .rcItem.Top, _
.rcItem.Right - 4, _
(.rcItem.Bottom - .rcItem.Top) \ 2 + 1 + .rcItem.Top, True
End If
Else
' This will remove or add a 3D raised box for checked/non-checked items
If bMenuItemChecked = False Then ThreeDbox lOffsets(1) + .rcItem.Left,
.rcItem.Top + 2, .rcItem.Right - 4 + lOffsets(1), .rcItem.Bottom - 2, True
End If
End If
'Select the old objects into the menu's DC
Call SelectObject(.hDC, hOldBr)
Call SelectObject(.hDC, hOldPen)
'Delete the ones we created
Call DeleteObject(hBR)
Call DeleteObject(hPen)
Call DeleteObject(hChkBr)
SetMenuFont False
End With
CustomDrawMenu = True ' set flag to prevent resending to form
Case WM_MEASUREITEM
Dim MeasureInfo As MEASUREITEMSTRUCT
'Get the MEASUREITEM info, basically submenu item height/width
Call CopyMemory(MeasureInfo, ByVal lParam, Len(MeasureInfo))
' only process menu items, other windows items send above message
' and we don't want to interfere with those. Also if we didn't
' process it, we don't touch it
If MenuData(hWndRedirect).SetMenuID(MeasureInfo.ItemId, lSubMenu, False,
False) = False Then Exit Function
If MeasureInfo.CtlType <> ODT_MENU Then Exit Function
IsSep = (((MenuData(hWndRedirect).Status And 2) = 2) And (Not
MenuData(hWndRedirect).Status And 16) = 16)
'Tell Windows how big our items are.
' add height of each item, add a buffer of 3 pixels top/bottom for text
MeasureInfo.ItemHeight = MenuData(hWndRedirect).ItemHeight
MeasureInfo.ItemWidth = MenuData(hWndRedirect).PanelWidth
'Return the information back to Windows
Call CopyMemory(ByVal lParam, MeasureInfo, Len(MeasureInfo))
CustomDrawMenu = True
Case WM_ENTERIDLE ' done displaying panel, let's stop drawing icons
bDrawIcon = False
End Select
End Function

Public Function HiWord(LongIn As Long) As Integer

50
'
=============================================================
========
' Returns the high integer of a long variable
'
=============================================================
========
Call CopyMemory(HiWord, ByVal VarPtr(LongIn) + 2, 2)
End Function

Public Function LoWord(LongIn As Long) As Integer


'
=============================================================
========
' Returns low integer of a long variable
'
=============================================================
========
Call CopyMemory(LoWord, LongIn, 2)
End Function

Private Function MakeLong(ByVal LoWord As Integer, ByVal HiWord As Integer)


As Long
'
=============================================================
========
' Converts 2 integers to a long variable
'
=============================================================
========
MakeLong = CLng(LoWord)
Call CopyMemory(ByVal VarPtr(MakeLong) + 2, HiWord, 2)
End Function

Private Function DetermineOS(Optional SetGraphicsModeDC As Long = 0) As


Integer
' Determine OS. Win98, for sure, seems to adjust the menu panel width
' to accomodate for the accelerator key within the menu. If the opposite
' adjustment isn't made, the panels wind up being wider than desired.
' Win98: adjustment needed
' Win2K: adjustment not needed
' WinNT: adjustment not needed
' WinXP: adjustment not needed
' Other O/S: ?

' The following are the platform, major version & minor version of OS to date
(acquired from MSDN)
Const os_Win95 = "1.4.0"
Const os_Win98 = "1.4.10"
Const os_WinNT4 = "2.4.0"

51
Const os_WinNT351 = "2.3.51"
Const os_Win2K = "2.5.0"
Const os_WinME = "1.4.90"
Const os_WinXP = "2.5.1"

Dim verinfo As OSVERSIONINFO, sVersion As String


verinfo.dwOSVersionInfoSize = Len(verinfo)
If (GetVersionEx(verinfo)) = 0 Then Exit Function ' use default 0
With verinfo
sVersion = .dwPlatformId & "." & .dwMajorVersion & "." & .dwMinorVersion
End With
' those where the iTabOffset is set are systems that I have seen the
' results on; otherwise, assume no adjustment is necessary
Select Case sVersion
Case os_Win98: iTabOffset = 32
Case os_Win2K: iTabOffset = 0
Case os_WinNT4: iTabOffset = 0
Case os_WinNT351
' Problems when printing rotated text
'According to MSDN, NT 3.51 only works on a setting of 2. Don't have the
opportunity to test this.
SetGraphicsMode SetGraphicsModeDC, 2
Case os_Win95
Case os_WinXP: iTabOffset = 0
Case os_WinME
End Select
End Function

Public Function GetFormHandle(hwnd As Long, Optional bIsMDI As Boolean) As


Long
Dim i As Long
For i = Forms.Count - 1 To 0 Step -1
If Forms(i).hwnd = hwnd Then Exit For
Next
If i > -1 Then
If TypeOf Forms(i) Is MDIForm Then bIsMDI = True
GetFormHandle = i
End If
End Function

Private Sub ReadMe()


'HOW TO USE THIS CLASS AND MODULES

'1. Each form that is subclassing menus must have the 2 lines of code entered into the
events shown below. The imagelist
'name is optional and must be provided if icons are to be displayed. Any loaded
form's imagelist can be used.

' MDI forms: If you are using MDI forms, if a child or parent is being subclassed,
' you must subclass each child and the parent. Additionally, the MDI children use the

52
' imagelist on the MDI form and MDI children do not reference the imagelist when
' the SetMenus command is called. All subclassed forms call the ReleaseMenus on
form unload.

' a. Form_Load: the last statement in this event should be: SetMenus [form
handle (.hWnd)] , [ImageList Name for Icons]
' -- for MDI children: SetMenus [form handle (.hWnd)] << uses the parent MDI
form's imagelist
' b. Form_Unload: the 1st statement in this event should be: ReleaseMenus [form
handle (.hWnd)]

'Example: SetMenus Me.hWnd, ImageList1

'2. DO NOT place breaks in the code when menus are subclassed or stop the code
when menus are subclassed.
'Doing so will crash VB. If you need to debug your code, set the public constant
bAmDebugging=True within the
'modModules module. This will prevent menus from being subclassed and will also
prevent menus from displaying icons.
'Be sure to set that constant = False when you want to see the icons.

'3. Do not put END statements in any of the forms that are subclassing menus. The
End statement may fire before
'the menus are released which will cause a critical error. The class and modules are
written to release themselves
'via the ReleaseMenus command.

'4. Assigning icons/bitmaps to your submenu items.

' a. Suggestion: Small icons (16x16) are best as far as clarity goes
' b. Suggeston: If bitmaps are used, use smaller bitmaps (16x16) vs larger bitmaps
(32x32)
' c. Add the following flag immediately in front of the menu's caption: {IMG:#}
' d. The # is the listimage icon index (1 thru n)
' e. If you want to supply a manually trapped accelerator key add that to the end of
the menu caption. See para 6.

' Example: menu caption is E&xit and image number 2 will be assigned to it and
Alt+F4 will be the
' manually trapped accelerator key

' {IMG:2}E&xit Alt+F4

'5. Optional transparency flag. By default, icons are NOT made to be transparent
since they probably are anyway.
'However, bitmaps by default ARE made to be transparentt. When transparency is
invoked, the top left pixel
'decides which color is made transparent throughout the image. Should you want to
force an icon/bitmap to

53
'be transparent or not be transparent, add the following code after the icon index in the
caption header flag:

' |N to prevent transparency or |Y to force transparency

' Example: I have a bitmap in the imagelist which has a colored background that I
do NOT want made transparent.
' Being a bitmap, by default, it will be made transparent. So I need to add then
|N option to the menu caption:

' {IMG:3|N}CD &Player Alt+P

'6. Accelerator keys. The menu builder allows you to select many accelerator keys and
will automatically trap them for you.
'With this class & modules you can add other accelerator keys not provided by the
menu builder (i.e., Alt+F4) and you
'can use the same accelerator key on more than one menu -- not allowed via the menu
builder.

' a. If you add an accelerator key manually (not via menu builder), you will need to
trap those keys in the form's Key_Down
' event by testing for KeyCode and Shift values

' b. In the examples above, manually adding an accelerator key is as simple as


placing it at the end of the caption.

' c. The modules will align the accelerator keys neatly before they are displayed on
the menu.

'7. To change the caption or image of a menu after the program is running, simply
change it in VB via the Caption property.
'The module will recognize the change and change the caption and/or assign the new
icon. If you want to remove the icon
'from the menu caption, do not include the {IMG:#} header or make the icon index =
zero. Note. The menu caption when
'referenced in VB will have the {IMG:#} header in the caption, but is stripped off
when displaying the menu.

' Example: Change {IMG:5}Color Option is On to read Off whle using the
same icon
' Changet to: {IMG:5}Color Option is Off << that's it!

'8. Checkmarks and enabled/disabled menu items. The modules will draw a sunken
box for menu items that are
'checked and include the icon inside the sunken box, if one is assigned; otherwise a
checkmark is placed inside
' the sunken box. Disabled menu items are made to imitate regular disabled items to
include the icon and caption.

54
'9. Separator bars. You can add text to the separator bars. While in the menu builder,
include the hyphen/dash to
'designate the menu item as a separator and then add the text immediately after.
{IMG:#} headers will not be
'recognized on separators, nor will accelerator keys be spaced with other accelerator
keys. Separator bars,
'regardless if they have text or not, are not clickable.

' a. By default, text on separator bars are one font point lower than the system menu
font and a font type of Tahoma.

' b. The color of the text on the separator will be the same color as the color used to
highlight a menu item with the mouse.

' c. If the bAmDebugging flag is set to True, then the separator bars will not be
disabled. Nor will they look disabled.

'10. These modules do not interfere with any menu events (i.e., click events, popup
position, etc, etc, etc are not affected)

'11. These modules to not draw parent level menus. In other words, menus that have
submenus are not drawn by the
'modules -- but their submenus are. The class and modules were written to use
Windows default menu style but add
'the capability of icons to submenus. Therefore, foreground colors, fonts and
background colors are not supported
'as this would not mirror the parent level menu items.

'12. The basic premis. Provide a somewhat small class and modules that can be
added to any project to support
'icons and make the subclassing easy. Other projects available on the web will draw
entire menus but come at
'a price -- large number of classes and modules added to each project or forcing DLLs
on other users.

'13. Sidebars. These are bitmaps or text along the left edge of a menu panel.
'You can add a picture or text by following these format rules. The images on
'a sidebar will be shrunk to fit if necessary, otherwise centered into the sidebar.
'When images are shrunk, they are done proportionally, therefore, there may be
'space around the image within the sidebar. If the formatted string is incorrect,
'no sidebar will be shown.

'That menu item MUST be visible, otherwise no sidebar will be drawn

'On any submenu of a menu, add the following formatted string


'Don't use spaces. Spaces below done for readability

' a. For images in controls like image controls, pictureboxes, etc:

' {SIDEBAR:control | BCOLOR:color }

55
' Example: {SIDEBAR:image1|BCOLOR:background}

' b. For images passed as handles. You must provide much more information
' {SIDEBAR:handle | BCOLOR:color }
' (SIDEBAR:120928|BCOLOR:background}

' The values for the tags in the above strings are as follows:
' If image is passed as a control, then the following is mandatory
' control: This is the control name with a picture property
' and must exist on the same form that is subclassing menus
' This also applies to MDI parents and children
' color: optional. Default is NONE. The color is used to fill in the space
' between the image and the sidebar when the image doesn't completely
' fill up the sidebar. Values for Color can be...
' 1. The numerical value of a color (i.e., BCOLOR:65535)
' 2. NONE. This will not fill in the space between image and sidebar
' 3. BACKGROUND. This will fill the space with the images top left pixel color
' If image is passed as a handle vs a form control, then this is mandatory:
' handle: the numerical picture.handle should be a bitmap! Icons will draw at 16x16

' c. For Text: don't use spaces except in the caption if needed. Spaces below done for
readability
' {SIDEBAR:TEXT | CAPTION:caption | FONT:fontname | FCOLOR:color |
BCOLOR:color | FSIZE:font_size}
' Optional flags can be added by preceding them with a pipe |
' BOLD, ITALIC, UNDERLINE, GRADIENT
' Example: {SIDEBAR:TEXT|CAPTION:La Volpe|FONT:Algerian|
FCOLOR:16777215|BCOLOR:255|FSIZE:12|GRADIENT}

' The values for the tags in the above string are as follows:

' caption: mandatory. The text you want displayed on the sidebar. The text font size
will be
' be 11 by default but reduced to fit the sidebar if needed
' fontname: Optional. The font to use. This font should be scalable. In other words,
' if the font size can be set as an odd number then don't use it.
' The default font will be Tahoma
' forecolor color: optional. Numerical value for the color of the text. Default is black
' backcolor color: optional. Numerical value for the back color of the sidebar.
Default is menu color
' font_size: optional. Whole number of a font size. Default is 11
' BOLD: optional. If supplied, font is bolded. Default is no bolding
' ITALIC: optional. If supplied, font is italicized. Default is no italics
' UNDERLINE: optional. If supplied, font is underlined. Default is no underlining
' GRADIENT: optional. If supplied, it is the word GRADIENT and will color the
sidebar
' in the backcolor, from black to backcolor, bottom to top.

'Suggestions? I will entertain any suggestions (always have). However, I do not plan
on making this class draw

56
'entire menus. I thought of the possibility of having icons & bitmaps on menus that
are not loaded into an
'imagelist. However, I don't immediately see why that would be necessary. If you
have a need for that
'capability, let me know -- I have already ran test code to make that happen.
End Sub

57
58
Program coding with visual
shots
Login page

 This feature is advanced security control.


 Each user have separate account with user name and password
 Three wrong entries of user name and password exits the program aumatically

Program coding for login

Dim pwctr As Integer

Private Sub cmdCancel_Click()


ReleaseMenus hwnd
End
End Sub

Private Sub cmdOK_Click()

Set userRS = New ADODB.Recordset


If txtUserName.Text <> "" Then

SQLstr = "Select * From userlist Where username = '" & Trim(txtUserName.Text)


& "'"
userRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If txtUserName.Text <> "Administrator" Then
If txtUserName.Text <> "administrator" Then
If txtUserName.Text <> "ADMINISTRATOR" Then
frmmain.mnusettingsystem.Enabled = False
frmmain.mnusettinguser.Enabled = False
Else
frmmain.mnusettingsystem.Enabled = True
frmmain.mnusettinguser.Enabled = True
End If
Else
frmmain.mnusettingsystem.Enabled = True

59
frmmain.mnusettinguser.Enabled = True
End If
Else
frmmain.mnusettingsystem.Enabled = True
frmmain.mnusettinguser.Enabled = True
End If
If Not userRS.EOF And Not userRS.BOF Then
If txtPassword.Text <> userRS!Password Then
pwctr = pwctr + 1
If pwctr = 1 Then
MsgBox "Invalid password! You have 2 tries remaining!", vbOKOnly +
vbInformation, "Information"
txtPassword.Text = ""
txtPassword.SetFocus

ElseIf pwctr = 2 Then


MsgBox "Invalid password! You only have 1 try remaining!", vbOKOnly +
vbInformation, "Information"
txtPassword.Text = ""
txtPassword.SetFocus
Else
ReleaseMenus hwnd
End
End If
Else
Unload Me
frmmain.Show
End If
Else
MsgBox "Invalid Username!", vbOKOnly + vbExclamation, "Warning.."
txtUserName.Text = ""
txtPassword.Text = ""
txtUserName.SetFocus
End If
Else
MsgBox "Invalid Username and Password!", vbOKOnly + vbExclamation,
"Warning.."
txtUserName.SetFocus
End If

End Sub

Private Sub Form_Load()


dbconnect
txtUserName.Text = GetSetting(App.EXEName, "TextBox", txtUserName.Name,
"")
End Sub

Private Sub Form_Unload(Cancel As Integer)


SaveSetting App.EXEName, "Textbox", txtUserName.Name, txtUserName.Text

60
End Sub

Private Sub txtPassword_KeyPress(KeyAscii As Integer)


If KeyAscii = 13 Then
If cmdOK.Enabled = True Then
cmdOK.Value = True
End If
End If
End Sub

Private Sub txtUserName_KeyPress(KeyAscii As Integer)


If KeyAscii = 13 Then
txtPassword.SetFocus
End If
End Sub

61
Main page

62
Program coding for main page

'this code is exit button to prompt a message box b4 exiting


Private Const clMsgbxEXITAPP As Long = vbDefaultButton1 + vbQuestion +
vbYesNo
Private mbIsDirty As Boolean

Private Sub Form_Load()


dbconnect
SetMenus hwnd, ImageList1

'this code is exit button to prompt a message box b4 exiting


Debug.Print "Form1::Load"
mbIsDirty = True
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)


'this code is exit button to prompt a message box b4 exiting
Debug.Print "Form1::QueryUnload"
If mbIsDirty Then
Cancel = CInt(pExitApp = False)
If Not Cancel Then
'-- We are ending the app. Clean up here.
Debug.Print "Clean Up time..."
Dim F As VB.Form
For Each F In Forms
Unload F
Next
ReleaseMenus hwnd
End If
End If
End Sub

Private Function pExitApp() As Boolean

63
'this code is exit button to prompt a message box b4 exiting
Debug.Print "Exit Application"
pExitApp = (MsgBox("Exit system?", clMsgbxEXITAPP, "Library") = vbYes)
End Function

Private Sub Form_Unload(Cancel As Integer)


'this code is exit button to prompt a message box b4 exiting
Debug.Print "Form1::Unload"
End Sub

Private Sub mnuabout_Click()


frmAbout.Show vbModal
End Sub

Private Sub mnufilebook_Click()


frmbookcatalog.Show vbModal
End Sub

Private Sub mnufileborrowerstud_Click()

End Sub

Private Sub mnufileborrower_Click()


frmborrower.Show vbModal
End Sub

Private Sub mnufileexit_Click()


If MsgBox("Exit system?", vbQuestion + vbYesNo) = vbNo Then
Exit Sub
End If
ReleaseMenus hwnd
End
End Sub

Private Sub mnufilefind_Click()


frmfind.Show vbModal
End Sub

Private Sub mnureportsbook_Click()


Set bookRS = New ADODB.Recordset
bookRS.Open "book_catalog", libCON, adOpenKeyset, adLockReadOnly
Set rptbook.DataSource = bookRS
rptbook.Show vbModal
End Sub

Private Sub mnureportsborrow_Click()


Set borrowerRS = New ADODB.Recordset
borrowerRS.Open "borrower_record", libCON, adOpenKeyset, adLockReadOnly
Set rptborrower.DataSource = borrowerRS
rptborrower.Show vbModal

64
End Sub

Private Sub mnureportscurrent_Click()


Set currentRS = New ADODB.Recordset
currentRS.Open "current_borrow", libCON, adOpenKeyset, adLockReadOnly
Set rptcurrent.DataSource = currentRS
rptcurrent.Show
End Sub

Private Sub mnureportsdue_Click()


Set currentRS = New ADODB.Recordset
SQLstr = "select * from current_borrow where due_date = date()"
currentRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
Set rptdue.DataSource = currentRS
rptdue.Show vbModal
End Sub

Private Sub mnureportsover_Click()


Set currentRS = New ADODB.Recordset
SQLstr = "select * from current_borrow where due_date < date()"
currentRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
Set rptoverdue.DataSource = currentRS
rptoverdue.Show vbModal
End Sub

Private Sub mnusettingsystemcategory_Click()


frmcategory.Show vbModal
End Sub

Private Sub mnusettingsystemcourse_Click()


frmcourse.Show vbModal
End Sub

Private Sub mnusettingsystemfee_Click()


frmsystem.Show vbModal
End Sub

Private Sub mnusettinguser_Click()


frmusers.Show vbModal
End Sub

Private Sub mnutransborrow_Click()


frmborrowing.Show vbModal
End Sub

Private Sub mnutransreturn_Click()


frmreturning.Show vbModal
End Sub
Book catalog

65
Program coding for book catalog

Dim x, y As Integer

Private Sub clear()


Combo1.Text = ""
Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
Text4.Text = ""
Text5.Text = ""
Combo2.Text = ""
Combo3.Text = ""
End Sub

Private Sub disable()


Combo1.Enabled = False
Text1.Enabled = False
Text2.Enabled = False
Text3.Enabled = False
Text4.Enabled = False
Text5.Enabled = False
Combo2.Enabled = False
Combo3.Enabled = False
End Sub

Private Sub enable()


Combo1.Enabled = True
Text1.Enabled = True
Text2.Enabled = True
Text3.Enabled = True
Text4.Enabled = True

66
Text5.Enabled = True
Combo2.Enabled = True
Combo3.Enabled = True
End Sub

Private Sub Command1_Click()


enable
Text1.SetFocus
Command1.Enabled = False
Command2.Enabled = True
Command5.Enabled = False
Command6.Caption = "&CANCEL"
End Sub

Private Sub Command2_Click()


If Text1.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text1.SetFocus
Exit Sub
End If
If Combo1.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Combo1.SetFocus
Exit Sub
End If
If Text2.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text2.SetFocus
Exit Sub
End If
If Text5.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text5.SetFocus
Exit Sub
End If
If Text3.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text3.SetFocus
Exit Sub
End If
If Text4.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text4.SetFocus
Exit Sub
End If
If Combo2.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Combo2.SetFocus
Exit Sub
End If

67
If Combo3.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Combo3.SetFocus
Exit Sub
End If

If Command2.Caption = "&SAVE" Then


Set bookRS = New ADODB.Recordset
SQLstr = "select access_no from book_catalog where access_no='" & Text1.Text
& "'"
bookRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If Not bookRS.EOF And Not bookRS.BOF Then
MsgBox "Accession No. already exist!", vbExclamation
Text1.SetFocus
Exit Sub
End If
If MsgBox("Save Book Catalog?", vbYesNo + vbQuestion) = vbYes Then
Set bookRS = New ADODB.Recordset
bookRS.Open "book_catalog", libCON, adOpenKeyset, adLockOptimistic
With bookRS
.AddNew
!access_no = Text1.Text
!category = Combo1.Text
!Title = Text2.Text
!Edition = Text5.Text
!Author = Text3.Text
!Publisher = Text4.Text
!yr_publish = Combo3.Text
!no_copy = Combo2.Text
!available_copy = Combo2.Text
.Update
.Close
End With
MsgBox "Book Catalog Successfully Saved!", vbInformation
End If
Else
If MsgBox("Update Book Catalog?", vbYesNo + vbQuestion) = vbYes Then
Set bookRS = New ADODB.Recordset
SQLstr = "Select * from book_catalog where access_no='" & Text1.Text & "'"
bookRS.Open SQLstr, libCON, adOpenKeyset, adLockOptimistic
With bookRS
!category = Combo1.Text
!Title = Text2.Text
!Edition = Text5.Text
!Author = Text3.Text
!Publisher = Text4.Text
!yr_publish = Combo3.Text
!no_copy = Combo2.Text
!available_copy = Combo2.Text
.Update

68
.Close
End With
MsgBox "Book Catalog Successfully Updated!", vbInformation
End If
End If
clear
disable
Command1.Enabled = True
Command2.Enabled = False
Command2.Caption = "&SAVE"
Command3.Enabled = False
Command4.Enabled = False
Command5.Enabled = True
Command6.Caption = "CL&OSE"
End Sub

Private Sub Command3_Click()


enable
Text1.Enabled = False
Combo1.SetFocus
Command2.Enabled = True
Command2.Caption = "&UPDATE"
Command3.Enabled = False
Command4.Enabled = False
Command7.Visible = False
End Sub

Private Sub Command4_Click()


If MsgBox("Sure To Delete Book Catalog?", vbQuestion + vbYesNo) = vbYes
Then
Set bookCMD = New ADODB.Command
SQLstr = "Delete * from book_catalog where access_no='" & Text1.Text & "'"
With bookCMD
.ActiveConnection = libCON
.CommandType = adCmdText
.CommandText = SQLstr
.Execute
End With
clear

MsgBox "Book Catalog Successfully Deleted!", vbInformation

Command1.Enabled = True
Command2.Enabled = False
Command3.Enabled = False
Command4.Enabled = False
Command5.Enabled = True
Command6.Caption = "CL&OSE"
Command7.Visible = False
End If

69
End Sub

Private Sub Command5_Click()


Text1.Enabled = True
Text1.SetFocus
Command1.Enabled = False
Command5.Enabled = False
Command6.Caption = "&CANCEL"
Command7.Visible = True
End Sub

Private Sub Command6_Click()


If Command6.Caption = "CL&OSE" Then
Unload Me
Else
clear
disable
Command1.Enabled = True
Command2.Enabled = False
Command3.Enabled = False
Command4.Enabled = False
Command5.Enabled = True
Command6.Caption = "CL&OSE"
Command7.Visible = False
End If
End Sub

Private Sub Command7_Click()


Set bookRS = New ADODB.Recordset
SQLstr = "Select * from book_catalog where access_no='" & Text1.Text & "'"
bookRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If bookRS.EOF And bookRS.BOF Then
MsgBox "Accession Number Not Found!", vbExclamation
Text1.SetFocus
Exit Sub
End If
With bookRS
Combo1.Text = !category
Text2.Text = !Title
Text3.Text = !Author
Text4.Text = !Publisher
Text5.Text = !Edition
Combo2.Text = !no_copy
Combo3.Text = !yr_publish
End With
Command3.Enabled = True
Command4.Enabled = True
End Sub

Private Sub Form_Load()

70
dbconnect
clear
disable

Set catRS = New ADODB.Recordset


catRS.Open "category", libCON, adOpenKeyset, adLockReadOnly
While catRS.EOF <> True
Combo1.AddItem catRS!category
catRS.MoveNext
Wend

x=1
While x <= 10
Combo2.AddItem x
x=x+1
Wend

y = 1601
While y <= 9999
Combo3.AddItem y
y=y+1
Wend

Command2.Enabled = False
Command3.Enabled = False
Command4.Enabled = False
Command7.Visible = False
End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)


If Command7.Visible = True Then
If KeyAscii = 13 Then
Command7.Value = True
End If
End If
End Sub

Borrowers
record

71
Program coding for borrower’s record
Private Sub clear()
Text5.Text = ""
Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
Option1.Value = False
Option2.Value = False
Combo1.Text = ""
Text4.Text = ""
MaskEdBox2.Text = "( ) - "
End Sub

Private Sub disable()


Text5.Enabled = False
Text1.Enabled = False
Text2.Enabled = False
Text3.Enabled = False
Option1.Enabled = False
Option2.Enabled = False
Text4.Enabled = False
Combo1.Enabled = False
MaskEdBox2.Enabled = False
End Sub

Private Sub enable()


Text5.Enabled = True
Text1.Enabled = True
Text2.Enabled = True
Text3.Enabled = True
Option1.Enabled = True
Option2.Enabled = True

72
Text4.Enabled = True
'Combo1.Enabled = True
MaskEdBox2.Enabled = True
End Sub

Private Sub Command1_Click()


enable
Text5.SetFocus
Command1.Enabled = False
Command2.Enabled = True
Command5.Enabled = False
Command6.Caption = "&CANCEL"
End Sub

Private Sub Command2_Click()


If Text5.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text5.SetFocus
Exit Sub
End If
If Text1.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text1.SetFocus
Exit Sub
End If
If Text2.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text2.SetFocus
Exit Sub
End If
If Text3.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text3.SetFocus
Exit Sub
End If
If Option1.Value = False And Option2.Value = False Then
MsgBox "Complete neccessary information", vbExclamation
Option1.SetFocus
Exit Sub
End If
If Option1.Value = True And Combo1.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Combo1.SetFocus
Exit Sub
End If
If Text4.Text = "" Then
MsgBox "Complete neccessary information", vbExclamation
Text4.SetFocus
Exit Sub
End If

73
If Command2.Caption = "&SAVE" Then
Set borrowerRS = New ADODB.Recordset
SQLstr = "select borrower_id from borrower_record where borrower_id='" &
Text5.Text & "'"
borrowerRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If Not borrowerRS.EOF And Not borrowerRS.BOF Then
MsgBox "Borrower ID already exist!", vbExclamation
Text5.SetFocus
Exit Sub
End If

If MsgBox("Save Borrower Record?", vbYesNo + vbQuestion) = vbYes Then


Set borrowerRS = New ADODB.Recordset
borrowerRS.Open "borrower_record", libCON, adOpenKeyset,
adLockOptimistic
With borrowerRS
.AddNew
!borrower_id = Text5.Text
!lname = Text1.Text
!fname = Text2.Text
!mI = Text3.Text
If Option1.Value = True Then
!Status = "Student"
Else
!Status = "Faculty / Employee"
End If
!course = Combo1.Text
!Add = Text4.Text
!contact = MaskEdBox2.Text
.Update
.Close
End With
MsgBox "Borrower Record Successfully Saved!", vbInformation
End If
Else
If MsgBox("Update Borrower Record?", vbYesNo + vbQuestion) = vbYes Then
Set borrowerRS = New ADODB.Recordset
SQLstr = "Select * from borrower_record where borrower_id='" & Text5.Text &
"'"
borrowerRS.Open SQLstr, libCON, adOpenKeyset, adLockOptimistic
With borrowerRS
!lname = Text1.Text
!fname = Text2.Text
!mI = Text3.Text
If Option1.Value = True Then
!Status = "Student"
Else
!Status = "Faculty / Employee"
End If

74
!course = Combo1.Text
!Add = Text4.Text
!contact = MaskEdBox2.Text
.Update
.Close
End With
MsgBox "Borrower Record Successfully Updated!", vbInformation
End If
End If

clear
disable
Command1.Enabled = True
Command2.Enabled = False
Command2.Caption = "&SAVE"
Command3.Enabled = False
Command4.Enabled = False
Command5.Enabled = True
Command6.Caption = "CL&OSE"
End Sub

Private Sub Command3_Click()


enable
Text5.Enabled = False
Text1.SetFocus
Combo1.Enabled = True
Command2.Enabled = True
Command2.Caption = "&UPDATE"
Command3.Enabled = False
Command4.Enabled = False
Command7.Visible = False
End Sub

Private Sub Command4_Click()


If MsgBox("Sure To Delete Borrower Record?", vbQuestion + vbYesNo) = vbYes
Then
Set borrowerCMD = New ADODB.Command
SQLstr = "Delete * from borrower_record where borrower_id='" & Text5.Text
& "'"
With borrowerCMD
.ActiveConnection = libCON
.CommandType = adCmdText
.CommandText = SQLstr
.Execute
End With
clear

MsgBox "Borrower Record Successfully Deleted!", vbInformation

Command1.Enabled = True

75
Command2.Enabled = False
Command3.Enabled = False
Command4.Enabled = False
Command5.Enabled = True
Command6.Caption = "CL&OSE"
Command7.Visible = False
End If
End Sub

Private Sub Command5_Click()


Text5.Enabled = True
Text5.SetFocus
Command1.Enabled = False
Command5.Enabled = False
Command6.Caption = "&CANCEL"
Command7.Visible = True
End Sub

Private Sub Command6_Click()


If Command6.Caption = "CL&OSE" Then
Unload Me
Else
clear
disable
Command1.Enabled = True
Command2.Enabled = False
Command3.Enabled = False
Command4.Enabled = False
Command5.Enabled = True
Command6.Caption = "CL&OSE"
Command7.Visible = False
End If
End Sub

Private Sub Command7_Click()


Set borrowerRS = New ADODB.Recordset
SQLstr = "Select * from borrower_record where borrower_id='" & Text5.Text &
"'"
borrowerRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If borrowerRS.EOF And borrowerRS.BOF Then
MsgBox "Borrower ID not valid!", vbExclamation
Text5.SetFocus
Exit Sub
End If
With borrowerRS
Text1.Text = !lname
Text2.Text = !fname
Text3.Text = !mI
If !Status = "Student" Then
Option1.Value = True

76
Else
Option2.Value = True
End If
Combo1.Text = !course
Text4.Text = !Add
MaskEdBox2.Text = !contact
End With
Command3.Enabled = True
Command4.Enabled = True
End Sub

Private Sub Form_Load()

dbconnect
clear
disable

Set courseRS = New ADODB.Recordset


courseRS.Open "course", libCON, adOpenKeyset, adLockReadOnly
While courseRS.EOF <> True
Combo1.AddItem courseRS!course
courseRS.MoveNext
Wend

Command2.Enabled = False
Command3.Enabled = False
Command4.Enabled = False
Command7.Visible = False
End Sub

Private Sub Option1_Click()


If Option1.Enabled = True Then
Combo1.Enabled = True
Combo1.Text = ""
End If
End Sub

Private Sub Option2_Click()


If Option2.Enabled = True Then
Combo1.Enabled = False
Combo1.Text = "n/a"
End If
End Sub

Private Sub Text5_KeyPress(KeyAscii As Integer)


If Command7.Visible = True Then
If KeyAscii = 13 Then
Command7.Value = True
End If
End If

77
End Sub

Finding books

This is an icon which is used to find the input data by clicking on it.

Program coding for finding of books

Private Sub SetListViewTo(ByVal xrs As ADODB.Recordset, Optional ByVal


strSMIcons As String = "", Optional ByVal strLRGIcons As String = "", Optional
ByVal clmWidth)
ListView1.ListItems.clear
xrs.MoveFirst
While Not xrs.EOF
Set Item = ListView1.ListItems.Add(, "_" & xrs.Fields(0).Value,
xrs.Fields(0).Value)
'Item.SubItems(1) = xrs!access_no
Item.SubItems(1) = xrs!Title
Item.SubItems(2) = xrs!Edition
Item.SubItems(3) = xrs!Author
Item.SubItems(4) = xrs!Publisher
Item.SubItems(5) = xrs!yr_publish
Item.SubItems(6) = xrs!no_copy
Item.SubItems(7) = xrs!available_copy
Item.SubItems(8) = xrs!borrow_copy
xrs.MoveNext
Wend
End Sub

78
Public Sub SetSectionViewTitle()

Set bookRS = New ADODB.Recordset


SQLstr = "SELECT * FROM book_catalog WHERE title='" & Text1.Text & "'"
bookRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If bookRS.EOF And bookRS.BOF Then
MsgBox "No title found!", vbInformation
Exit Sub
End If
SetListViewTo bookRS, 2, 2, clmWidth

End Sub

Public Sub SetSectionViewAuthor()

Set bookRS = New ADODB.Recordset


SQLstr = "SELECT * FROM book_catalog WHERE author='" & Text1.Text & "'"
bookRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If bookRS.EOF And bookRS.BOF Then
MsgBox "No Author found!", vbInformation
Exit Sub
End If

SetListViewTo bookRS, 2, 2, clmWidth


End Sub

Private Sub Command1_Click()


If Option1.Value = True Then
SetSectionViewTitle
Else
SetSectionViewAuthor
End If
End Sub

Private Sub Command2_Click()


Unload Me
End Sub

Private Sub Form_Load()


Option1.Value = True
End Sub

Private Sub Option1_Click()


If Option1.Value = True Then
Label1.Caption = "Search by Title :"
End If
End Sub

79
Private Sub Option2_Click()
If Option2.Value = True Then
Label1.Caption = "Search by Author :"
End If
End Sub

Private Sub Text1_Change()


ListView1.ListItems.clear
End Sub

Borrowing of books

This is a command button which is used to


borrow the books by entering the borrower id. Automatically name and status will be
displayed

In the books information type the accestion no


of book which you want to borrow.

By clicking save command button library


transaction successfully saved.

80
Program coding for borrowing of books

Dim xcat, xedition, xauthor, xpublisher, xyr_publish As String


Dim xavail_copy As Integer

Private Sub SetListViewTo(ByVal xrs As ADODB.Recordset, Optional ByVal


strSMIcons As String = "", Optional ByVal strLRGIcons As String = "", Optional
ByVal clmWidth)
ListView1.ListItems.clear
xrs.MoveFirst
While Not xrs.EOF
Set Item = ListView1.ListItems.Add(, "_" & xrs.Fields(0).Value,
xrs.Fields(0).Value)
Item.SubItems(1) = xrs!access_no
Item.SubItems(2) = xrs!Title
Item.SubItems(3) = xrs!Edition
Item.SubItems(4) = xrs!Author
Item.SubItems(5) = xrs!Publisher
Item.SubItems(6) = xrs!yr_publish
xrs.MoveNext
Wend
End Sub

Public Sub SetSectionView()

Set currentRS = New ADODB.Recordset


SQLstr = "SELECT * FROM current_borrow WHERE borrower_id='" &
Text1.Text & "'"
currentRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If currentRS.EOF And currentRS.BOF Then
Exit Sub
End If
SetListViewTo currentRS, 2, 2, clmWidth
End Sub

Private Sub clear()


Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
Text4.Text = ""

81
Combo1.Text = ""
DTPicker1.Value = Date
End Sub

Private Sub disable()


Text1.Enabled = False
Text2.Enabled = False
Text3.Enabled = False
Text4.Enabled = False
Combo1.Enabled = False
DTPicker1.Enabled = False
End Sub

Private Sub Combo1_Change()


Dim strPart As String, iLoop As Integer, iStart As Integer, strItem As String
If Not auto And Combo1.Text <> "" Then
iStart = Combo1.SelStart
strPart = Left$(Combo1.Text, iStart)
For iLoop = 0 To Combo1.ListCount - 1
strItem = UCase$(Combo1.List(iLoop))
If strItem Like UCase$(strPart & "*") And strItem <> UCase$(Combo1.Text)
Then
auto = True
Combo1.SelText = Mid$(Combo1.List(iLoop), iStart + 1)
Combo1.SelStart = iStart
Combo1.SelLength = Len(Combo1.Text) - iStart
auto = False
Exit For
End If
Next iLoop
End If

If Combo1.Text = "" Then


Text4.Text = ""
xcat = ""
xedition = ""
xauthor = ""
xpublisher = ""
xyr_publish = ""
End If
If Combo1.Text <> "" And Text4.Text <> "" Then
Command2.Enabled = True
Else
Command2.Enabled = False
End If
End Sub

Private Sub Combo1_Click()


Set bookRS = New ADODB.Recordset
SQLstr = "Select * from book_catalog where access_no='" & Combo1.Text & "'"

82
bookRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
With bookRS
Text4.Text = !Title
xcat = !category
xedition = !Edition
xauthor = !Author
xpublisher = !Publisher
xyr_publish = !yr_publish
xavail_copy = !available_copy
End With

If Combo1.Text <> "" And Text4.Text <> "" Then


Command2.Enabled = True
Else
Command2.Enabled = False
End If
End Sub

Private Sub Combo1_KeyDown(KeyCode As Integer, Shift As Integer)


If KeyCode = vbKeyBack Or KeyCode = vbKeyDelete Then
auto = True
Combo1.SelText = ""
auto = False
ElseIf KeyCode = vbKeyReturn Then
Combo1_LostFocus
Combo1.SelStart = Len(Combo1.Text)
End If
End Sub

Private Sub Combo1_KeyPress(KeyAscii As Integer)


If KeyAscii = 13 Then
Set bookRS = New ADODB.Recordset
SQLstr = "Select * from book_catalog where access_no='" & Combo1.Text & "'"
bookRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If bookRS.EOF And bookRS.BOF Then
Exit Sub
End If
With bookRS
Text4.Text = !Title
xcat = !category
xedition = !Edition
xauthor = !Author
xpublisher = !Publisher
xyr_publish = !yr_publish
xavail_copy = !available_copy
End With

If Combo1.Text <> "" And Text4.Text <> "" Then


Command2.Enabled = True
Else

83
Command2.Enabled = False
End If
End If
End Sub

Private Sub Combo1_LostFocus()


Dim iLoop As Integer
If Combo1.Text <> "" Then
For iLoop = 0 To Combo1.ListCount - 1
If UCase$(Combo1.List(iLoop)) = UCase$(Combo1.Text) Then
auto = True
Combo1.Text = Combo1.List(iLoop)
auto = False
Exit For
End If
Next iLoop
End If
End Sub

Private Sub Command1_Click()


Text1.Enabled = True
Text1.SetFocus
Command1.Enabled = False
Command6.Caption = "&CANCEL"
Command7.Visible = True
End Sub

Private Sub Command3_Click()


Text1.Enabled = False
Command7.Visible = False
frmaddbook.Show vbModal
End Sub

Private Sub Command2_Click()


If xavail_copy = 0 Then
MsgBox "There is no available copy of this book!", vbInformation
Combo1.SetFocus
Exit Sub
End If

Set currentRS = New ADODB.Recordset


SQLstr = "Select * from current_borrow where access_no='" & Combo1.Text & "'"
& " and borrower_id='" & Text1.Text & "'"
currentRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If Not currentRS.EOF And Not currentRS.BOF Then
MsgBox "Borrower's cannot borrow 2 same book title!", vbInformation
Combo1.SetFocus
Exit Sub
End If

84
Set currentRS = New ADODB.Recordset
currentRS.Open "current_borrow", libCON, adOpenKeyset, adLockOptimistic
With currentRS
.AddNew
!access_no = Combo1.Text
!Title = Text4.Text
!category = xcat
!Edition = xedition
!Author = xauthor
!Publisher = xpublisher
!yr_publish = xyr_publish
!borrow_date = Label4.Caption
If DTPicker1.Enabled = True Then
!due_date = DTPicker1.Value
End If
!borrower_id = Text1.Text
!Name = Text2.Text
!Status = Text3.Text
.Update
.Close
End With

Set bookRS = New ADODB.Recordset


SQLstr = "select * from book_catalog where access_no='" & Combo1.Text & "'"
bookRS.Open SQLstr, libCON, adOpenKeyset, adLockOptimistic
With bookRS
!available_copy = xavail_copy - 1
!borrow_copy = !borrow_copy + 1
.Update
.Close
End With

SetSectionView
MsgBox "Library Transaction Successfully Saved!", vbInformation

If ListView1.ListItems.Count = 3 Then
'MsgBox "Borrower reach the maximum book that can be borrowed at a
time!", vbExclamation
clear
disable
ListView1.ListItems.clear
Command1.Enabled = True
Command2.Enabled = False
Command6.Caption = "CL&OSE"
Exit Sub
End If

If MsgBox("Borrow Another Book?", vbQuestion + vbYesNo) = vbYes Then


Combo1.Text = ""
Combo1.SetFocus

85
Exit Sub
End If
clear
disable
ListView1.ListItems.clear
Command1.Enabled = True
Command2.Enabled = False
Command6.Caption = "CL&OSE"
End Sub

Private Sub Command6_Click()


If Command6.Caption = "CL&OSE" Then
Unload Me
Else
clear
disable
Command1.Enabled = True
Command2.Enabled = False
Command6.Caption = "CL&OSE"
Command7.Visible = False
End If
End Sub

Private Sub Command7_Click()


Set borrowerRS = New ADODB.Recordset
SQLstr = "Select * from borrower_record where borrower_id='" & Text1.Text &
"'"
borrowerRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If borrowerRS.EOF And borrowerRS.BOF Then
MsgBox "Borrower ID not valid!", vbExclamation
Text1.SetFocus
Exit Sub
End If
With borrowerRS
Text2.Text = !lname & ", " & !fname & " " & !mI
Text3.Text = !Status
End With

SetSectionView
If ListView1.ListItems.Count = 3 Then
MsgBox "Borrower Already Borrowed 3 Books!", vbExclamation
clear
ListView1.ListItems.clear
Text1.Text = ""
Text1.SetFocus
Exit Sub
End If
If Text3.Text = "Faculty / Employee" Then
DTPicker1.Enabled = False
Else

86
DTPicker1.Enabled = True
End If
Combo1.Enabled = True
Combo1.SetFocus
Text1.Enabled = False
Command7.Visible = False
End Sub

Private Sub Form_Load()


dbconnect
clear
disable
Label4.Caption = Date
Command2.Enabled = False
Command7.Visible = False

'accession number
Set bookRS = New ADODB.Recordset
bookRS.Open "book_catalog", libCON, adOpenKeyset, adLockReadOnly
While bookRS.EOF <> True
Combo1.AddItem bookRS!access_no
bookRS.MoveNext
Wend
End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)


If KeyAscii = 13 Then
Command7.Value = True
End If
End Sub

Returning of books

87
This is a command button which is used
to return the borrowed books by entering the accession no the title of the book
is displayed in title box.
Then enter borrower id in borrower’s
information in borrower id box. Name of the person and status is displayed
In case of overdue the charge of the fine
charge is displayed

By clicking save command button library


transaction successfully saved.

88
Program code for returning of books

Dim xaccess_no, xborrower_id As String

Private Sub clear()


Combo1.Text = ""
Text1.Text = ""
Combo2.Text = ""
Text2.Text = ""
Text3.Text = ""
Text4.Text = Date
Text5.Text = Date
Label11.Caption = "0"
Label12.Caption = "0.00"
Label13.Caption = "0.00"
End Sub

Private Sub Combo1_Change()


Dim strPart As String, iLoop As Integer, iStart As Integer, strItem As String
If Not auto And Combo1.Text <> "" Then
iStart = Combo1.SelStart
strPart = Left$(Combo1.Text, iStart)
For iLoop = 0 To Combo1.ListCount - 1
strItem = UCase$(Combo1.List(iLoop))
If strItem Like UCase$(strPart & "*") And strItem <> UCase$(Combo1.Text)
Then
auto = True
Combo1.SelText = Mid$(Combo1.List(iLoop), iStart + 1)
Combo1.SelStart = iStart
Combo1.SelLength = Len(Combo1.Text) - iStart
auto = False
Exit For
End If
Next iLoop
End If

If Combo1.Text = "" Then


Text1.Text = ""
Combo2.Text = ""
End If

89
If Combo1.Text <> "" And Text1.Text <> "" Then
Combo2.Enabled = True
Else
Combo2.Enabled = False
End If
End Sub

Private Sub Combo1_Click()


Set currentRS = New ADODB.Recordset
SQLstr = "Select * from current_borrow where access_no='" & Combo1.Text & "'"
currentRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If currentRS.EOF And currentRS.BOF Then
Exit Sub
End If
With currentRS
Text1.Text = !Title
Combo2.clear
xborrower_id = ""
While .EOF <> True
If !borrower_id = xborrower_id Then
.MoveNext
Else
Combo2.AddItem !borrower_id
xborrower_id = !borrower_id
.MoveNext
End If
Wend
Text2.Text = ""
Text3.Text = ""
Text4.Text = Date
Text5.Text = Date
End With

If Combo1.Text <> "" And Text1.Text <> "" Then


Combo2.Enabled = True
Else
Combo2.Enabled = False
End If
End Sub

Private Sub Combo1_KeyDown(KeyCode As Integer, Shift As Integer)

90
If KeyCode = vbKeyBack Or KeyCode = vbKeyDelete Then
auto = True
Combo1.SelText = ""
auto = False
ElseIf KeyCode = vbKeyReturn Then
Combo1_LostFocus
Combo1.SelStart = Len(Combo1.Text)
End If
End Sub

Private Sub Combo1_KeyPress(KeyAscii As Integer)


If KeyAscii = 13 Then
Set currentRS = New ADODB.Recordset
SQLstr = "Select * from current_borrow where access_no='" & Combo1.Text & "'"
currentRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If currentRS.EOF And currentRS.BOF Then
Exit Sub
End If
With currentRS
Text1.Text = !Title
Combo2.clear
xborrower_id = ""
While .EOF <> True
If !borrower_id = xborrower_id Then
.MoveNext
Else
Combo2.AddItem !borrower_id
xborrower_id = !borrower_id
.MoveNext
End If
Wend
Text2.Text = ""
Text3.Text = ""
Text4.Text = Date
Text5.Text = Date
End With

If Combo1.Text <> "" And Text1.Text <> "" Then


Combo2.Enabled = True
Else
Combo2.Enabled = False

91
End If
End If
End Sub

Private Sub Combo1_LostFocus()


Dim iLoop As Integer
If Combo1.Text <> "" Then
For iLoop = 0 To Combo1.ListCount - 1
If UCase$(Combo1.List(iLoop)) = UCase$(Combo1.Text) Then
auto = True
Combo1.Text = Combo1.List(iLoop)
auto = False
Exit For
End If
Next iLoop
End If
End Sub

Private Sub combo2_Change()


Dim strPart As String, iLoop As Integer, iStart As Integer, strItem As String
If Not auto And Combo2.Text <> "" Then
iStart = Combo2.SelStart
strPart = Left$(Combo2.Text, iStart)
For iLoop = 0 To Combo2.ListCount - 1
strItem = UCase$(Combo2.List(iLoop))
If strItem Like UCase$(strPart & "*") And strItem <> UCase$(Combo2.Text)
Then
auto = True
Combo2.SelText = Mid$(Combo2.List(iLoop), iStart + 1)
Combo2.SelStart = iStart
Combo2.SelLength = Len(Combo2.Text) - iStart
auto = False
Exit For
End If
Next iLoop
End If

If Combo2.Text = "" Then


Text2.Text = ""
Text3.Text = ""
Text4.Text = Date

92
Text5.Text = Date
End If
End Sub

Private Sub Combo2_Click()


Set currentRS = New ADODB.Recordset
SQLstr = "select * from current_borrow where borrower_id='" & Combo2.Text & "'"
currentRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If currentRS.EOF And currentRS.BOF Then
Exit Sub
End If
With currentRS
Text2.Text = !Name
Text3.Text = !Status
Text4.Text = !borrow_date
On Error Resume Next
Text5.Text = !due_date
End With
End Sub

Private Sub combo2_KeyDown(KeyCode As Integer, Shift As Integer)


If KeyCode = vbKeyBack Or KeyCode = vbKeyDelete Then
auto = True
Combo2.SelText = ""
auto = False
ElseIf KeyCode = vbKeyReturn Then
combo2_LostFocus
Combo2.SelStart = Len(Combo2.Text)
End If
End Sub

Private Sub Combo2_KeyPress(KeyAscii As Integer)


If KeyAscii = 13 Then
Set currentRS = New ADODB.Recordset
SQLstr = "select * from current_borrow where borrower_id='" & Combo2.Text & "'"
currentRS.Open SQLstr, libCON, adOpenKeyset, adLockReadOnly
If currentRS.EOF And currentRS.BOF Then
Exit Sub
End If
With currentRS
Text2.Text = !Name

93
Text3.Text = !Status
Text4.Text = !borrow_date
On Error Resume Next
Text5.Text = !due_date
End With
End If
End Sub

Private Sub combo2_LostFocus()


Dim iLoop As Integer
If Combo2.Text <> "" Then
For iLoop = 0 To Combo2.ListCount - 1
If UCase$(Combo2.List(iLoop)) = UCase$(Combo2.Text) Then
auto = True
Combo2.Text = Combo2.List(iLoop)
auto = False
Exit For
End If
Next iLoop
End If
End Sub

Private Sub Command1_Click()


If currentRS.EOF And currentRS.BOF Then
MsgBox "There is no books currently borrowed!", vbExclamation
Exit Sub
End If
Combo1.Enabled = True
Combo1.SetFocus
Command1.Enabled = False
Command6.Caption = "&CANCEL"
End Sub

Private Sub Command2_Click()


Set bookRS = New ADODB.Recordset
SQLstr = "Select * from book_catalog where access_no='" & Combo1.Text & "'"
bookRS.Open SQLstr, libCON, adOpenKeyset, adLockOptimistic
With bookRS
!available_copy = !available_copy + 1
!borrow_copy = !borrow_copy - 1
.Update

94
.Close
End With

Set currentCMD = New ADODB.Command


SQLstr = "Delete * from current_borrow where access_no='" & Combo1.Text & "'"
& " and borrower_id='" & Combo2.Text & "'"
With currentCMD
.ActiveConnection = libCON
.CommandType = adCmdText
.CommandText = SQLstr
.Execute
End With
clear
Combo1.Enabled = False
Command1.Enabled = True
Command2.Enabled = False
Command6.Caption = "CL&OSE"

MsgBox "Library Transaction Successfully Saved!", vbInformation

Set currentRS = New ADODB.Recordset


currentRS.Open "current_borrow", libCON, adOpenKeyset, adLockReadOnly
Combo1.clear
xaccess_no = ""
While currentRS.EOF <> True
If currentRS!access_no = xaccess_no Then
currentRS.MoveNext
Else
Combo1.AddItem currentRS!access_no
xaccess_no = currentRS!access_no
currentRS.MoveNext
End If
Wend
End Sub

Private Sub Command6_Click()


If Command6.Caption = "CL&OSE" Then
Unload Me
Else
clear
Combo1.Enabled = False

95
Combo2.Enabled = False
Command1.Enabled = True
Command2.Enabled = False
Command6.Caption = "CL&OSE"
End If
End Sub

Private Sub Form_Load()


dbconnect
clear
Combo1.Enabled = False
Combo2.Enabled = False
Command2.Enabled = False

Set currentRS = New ADODB.Recordset


currentRS.Open "current_borrow", libCON, adOpenKeyset, adLockReadOnly
xaccess_no = ""
While currentRS.EOF <> True
If currentRS!access_no = xaccess_no Then
currentRS.MoveNext
Else
Combo1.AddItem currentRS!access_no
xaccess_no = currentRS!access_no
currentRS.MoveNext
End If
Wend
End Sub

Private Sub Text2_Change()


If Text2.Text = "" Then
Command2.Enabled = False
Else
Command2.Enabled = True
End If

End Sub

Private Sub Text5_Change()


If Date > DateValue(Text5.Text) Then
Label11.Caption = Date - DateValue(Text5.Text)
Set feeRS = New ADODB.Recordset

96
feeRS.Open "charge", libCON, adOpenKeyset, adLockReadOnly
Label12.Caption = feeRS!charge_fee
Label13.Caption = Val(Label11.Caption) * Val(Label12.Caption)
Label12.Caption = Format(Label12.Caption, "###.00")
Label13.Caption = Format(Label13.Caption, "###.00")
Else
Label11.Caption = "0"
Label12.Caption = "0.00"
Label13.Caption = "0.00"
End If
End Sub

Reports section
Books masters list

Borrowers master list

97
Currently borrowed books list

Over due books list

98
Settings section
Settings in library management systems

This is a command button which is used to add the


book category in the list of books

99
This is a command button which is used to delete
the book category in the list of books

Program coding for updating book category

Private Sub Command1_Click()


frmaddcategory.Show vbModal
End Sub

Private Sub Command2_Click()


Set catCMD = New ADODB.Command
SQLstr = "DELETE * FROM category where category ='" & List1.Text & "'"
With catCMD
.ActiveConnection = libCON
.CommandType = adCmdText
.CommandText = SQLstr
.Execute
End With
List1.clear
listrefresh

Command2.Enabled = False
End Sub

Private Sub Command3_Click()


Unload Me
End Sub

Private Sub Form_Load()


dbconnect
listrefresh
End Sub

Private Sub List1_Click()


If List1.Text <> Empty Then
Command2.Enabled = True
End If
End Sub

Private Sub listrefresh()


Set catRS = New ADODB.Recordset
catRS.Open "category", libCON, adOpenKeyset, adLockReadOnly
While catRS.EOF <> True
List1.AddItem catRS!category
catRS.MoveNext
Wend
End Sub

100
User management

This is a command button which is used to add new


user account by entering the username and password and by verifying it and save.
User account is created.

Program coding for user management

Private Sub cmdAdd_Click()


frmadduser.Show vbModal
End Sub

Private Sub cmdCancel_Click()


Unload Me
End Sub

Private Sub cmdchange_Click()

'users
Set userRS = New ADODB.Recordset
SQLstr = "SELECT * FROM userlist where username='" & List1.Text & "'"

101
userRS.Open SQLstr, libCON, adOpenKeyset, adLockOptimistic

frmchange.lblusername.Caption = userRS!UserName

frmchange.Show vbModal

End Sub

Private Sub cmdDelete_Click()

If List1.Text = "Administrator" Then


MsgBox "Default User!", vbOKOnly + vbExclamation, "Warning..."
List1.Text = ""
cmdDelete.Enabled = False
cmdchange.Enabled = False
Exit Sub
End If
If MsgBox("Delete Username and Password?", vbYesNo + vbQuestion, "DELETING
USER") = vbNo Then
List1.Text = ""
cmdDelete.Enabled = False
cmdchange.Enabled = False
Exit Sub
End If

'users
Set userCMD = New ADODB.Command
SQLstr = "DELETE * FROM userlist where username ='" & List1.Text & "'"
With userCMD
.ActiveConnection = libCON
.CommandType = adCmdText
.CommandText = SQLstr
.Execute
End With
List1.clear
Call listrefresh

cmdDelete.Enabled = False
cmdchange.Enabled = False

MsgBox "Username and Password Deleted!", vbOKOnly + vbInformation,


"Information"

End Sub

Private Sub Form_Load()


dbconnect
Call listrefresh
End Sub

102
Private Sub listrefresh()
'users
Set userRS = New ADODB.Recordset
userRS.Open "userlist", libCON, adOpenKeyset, adLockReadOnly

While userRS.EOF <> True


List1.AddItem userRS!UserName
userRS.MoveNext
Wend

End Sub

Private Sub List1_Click()


If List1.Text <> Empty Then
cmdDelete.Enabled = True
cmdchange.Enabled = True
End If
End Sub

About

Program code for about

103
AM JAIN LIBRARY SYSTEMS

Option Explicit

' Reg Key Security Options...


Const READ_CONTROL = &H20000
Const KEY_QUERY_VALUE = &H1
Const KEY_SET_VALUE = &H2
Const KEY_CREATE_SUB_KEY = &H4
Const KEY_ENUMERATE_SUB_KEYS = &H8
Const KEY_NOTIFY = &H10
Const KEY_CREATE_LINK = &H20
Const KEY_ALL_ACCESS = KEY_QUERY_VALUE + KEY_SET_VALUE + _
KEY_CREATE_SUB_KEY + KEY_ENUMERATE_SUB_KEYS + _
KEY_NOTIFY + KEY_CREATE_LINK + READ_CONTROL

' Reg Key ROOT Types...


Const HKEY_LOCAL_MACHINE = &H80000002
Const ERROR_SUCCESS = 0
Const REG_SZ = 1 ' Unicode nul terminated string
Const REG_DWORD = 4 ' 32-bit number

Const gREGKEYSYSINFOLOC = "SOFTWARE\Microsoft\Shared Tools Location"


Const gREGVALSYSINFOLOC = "MSINFO"
Const gREGKEYSYSINFO = "SOFTWARE\Microsoft\Shared Tools\MSINFO"
Const gREGVALSYSINFO = "PATH"

Private Declare Function RegOpenKeyEx Lib "advapi32" Alias "RegOpenKeyExA"


(ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long,
ByVal samDesired As Long, ByRef phkResult As Long) As Long
Private Declare Function RegQueryValueEx Lib "advapi32" Alias
"RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal
lpReserved As Long, ByRef lpType As Long, ByVal lpData As String, ByRef
lpcbData As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32" (ByVal hKey As Long) As
Long

Private Sub cmdSysInfo_Click()


Call StartSysInfo
End Sub

Private Sub cmdOK_Click()


Unload Me

104
End Sub

Public Sub StartSysInfo()


On Error GoTo SysInfoErr

Dim rc As Long
Dim SysInfoPath As String

' Try To Get System Info Program Path\Name From Registry...


If GetKeyValue(HKEY_LOCAL_MACHINE, gREGKEYSYSINFO,
gREGVALSYSINFO, SysInfoPath) Then
' Try To Get System Info Program Path Only From Registry...
ElseIf GetKeyValue(HKEY_LOCAL_MACHINE, gREGKEYSYSINFOLOC,
gREGVALSYSINFOLOC, SysInfoPath) Then
' Validate Existance Of Known 32 Bit File Version
If (Dir(SysInfoPath & "\MSINFO32.EXE") <> "") Then
SysInfoPath = SysInfoPath & "\MSINFO32.EXE"

' Error - File Can Not Be Found...


Else
GoTo SysInfoErr
End If
' Error - Registry Entry Can Not Be Found...
Else
GoTo SysInfoErr
End If

Call Shell(SysInfoPath, vbNormalFocus)

Exit Sub
SysInfoErr:
MsgBox "System Information Is Unavailable At This Time", vbOKOnly
End Sub

Public Function GetKeyValue(KeyRoot As Long, KeyName As String, SubKeyRef


As String, ByRef KeyVal As String) As Boolean
Dim i As Long ' Loop Counter
Dim rc As Long ' Return Code
Dim hKey As Long ' Handle To An Open Registry Key
Dim hDepth As Long '
Dim KeyValType As Long ' Data Type Of A Registry Key
Dim tmpVal As String ' Tempory Storage For A Registry
Key Value
Dim KeyValSize As Long ' Size Of Registry Key Variable

'------------------------------------------------------------
' Open RegKey Under KeyRoot {HKEY_LOCAL_MACHINE...}
'------------------------------------------------------------
rc = RegOpenKeyEx(KeyRoot, KeyName, 0, KEY_ALL_ACCESS, hKey) ' Open
Registry Key

105
If (rc <> ERROR_SUCCESS) Then GoTo GetKeyError ' Handle Error...

tmpVal = String$(1024, 0) ' Allocate Variable Space


KeyValSize = 1024 ' Mark Variable Size

'------------------------------------------------------------
' Retrieve Registry Key Value...
'------------------------------------------------------------
rc = RegQueryValueEx(hKey, SubKeyRef, 0, _
KeyValType, tmpVal, KeyValSize) ' Get/Create Key Value

If (rc <> ERROR_SUCCESS) Then GoTo GetKeyError ' Handle Errors

If (Asc(Mid(tmpVal, KeyValSize, 1)) = 0) Then ' Win95 Adds Null


Terminated String...
tmpVal = Left(tmpVal, KeyValSize - 1) ' Null Found, Extract From
String
Else ' WinNT Does NOT Null Terminate String...
tmpVal = Left(tmpVal, KeyValSize) ' Null Not Found, Extract String
Only
End If
'------------------------------------------------------------
' Determine Key Value Type For Conversion...
'------------------------------------------------------------
Select Case KeyValType ' Search Data Types...
Case REG_SZ ' String Registry Key Data Type
KeyVal = tmpVal ' Copy String Value
Case REG_DWORD ' Double Word Registry Key Data
Type
For i = Len(tmpVal) To 1 Step -1 ' Convert Each Bit
KeyVal = KeyVal + Hex(Asc(Mid(tmpVal, i, 1))) ' Build Value Char. By
Char.
Next
KeyVal = Format$("&h" + KeyVal) ' Convert Double Word To
String
End Select

GetKeyValue = True ' Return Success


rc = RegCloseKey(hKey) ' Close Registry Key
Exit Function ' Exit

GetKeyError: ' Cleanup After An Error Has Occured...


KeyVal = "" ' Set Return Val To Empty String
GetKeyValue = False ' Return Failure
rc = RegCloseKey(hKey) ' Close Registry Key
End Function

Private Sub lblDescription_Click()

106
End Sub

107
SUPPORTS
• Mastering Visual Basic 6.0
• Visual Basic Programming Black Book
• MSDN Library
• Microsoft Windows Access 2003 Help

108

Das könnte Ihnen auch gefallen