/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "stdafx.h" #include "nsadrlst.h" #ifdef __APIAPIDLL #include "festuff.h" #else #include "compstd.h" #endif #include "resource.h" #define IDM_HEADER 8192 #define MAX_HEADER_ITEMS 20 //============================================================ CNSAddressList CNSAddressList::CNSAddressList() { m_hPenNormal = ::CreatePen(PS_SOLID,0,GetSysColor(COLOR_WINDOW)); m_hPenGrid = ::CreatePen(PS_SOLID,0,RGB(202,202,255)); m_hPenGrey = ::CreatePen(PS_SOLID, 0, RGB(202,202,255)); m_hBrushNormal = ::CreateSolidBrush(GetSysColor(COLOR_WINDOW)); m_lastIndex = 0; m_iDefaultBitmapId = 0; m_bDrawTypeList = FALSE; m_bArrowDown = FALSE; m_iFieldControlWidth = 0; m_iBitmapWidth = 0; m_iTypeBitmapWidth = 0; m_pNameField = new CNSAddressNameEditField; m_pAddressTypeList = new CNSAddressTypeControl; m_iItemHeight = 0; m_pIAddressParent = NULL; m_bCreated = FALSE; m_hTextFont = NULL; m_bParse = TRUE; } LRESULT CNSAddressList::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_ERASEBKGND: return DoEraseBkgnd(m_hWnd,(HDC)wParam); case WM_SETFOCUS: CListBox::DefWindowProc(message,wParam,lParam); DoSetFocus((HWND)wParam); return 0; case WM_KILLFOCUS: DoKillFocus((HWND)wParam); break; case WM_LBUTTONDOWN: { POINT point; CListBox::DefWindowProc(message,wParam,lParam); point.x = LOWORD(lParam); // horizontal position of cursor point.y = HIWORD(lParam); // vertical position of cursor DoLButtonDown(m_hWnd,wParam,&point); } return 0; case WM_LBUTTONUP: { POINT point; CListBox::DefWindowProc(message,wParam,lParam); point.x = LOWORD(lParam); // horizontal position of cursor point.y = HIWORD(lParam); // vertical position of cursor DoLButtonUp(m_hWnd,wParam,&point); } return 0; case WM_VSCROLL: { CListBox::DefWindowProc(message,wParam,lParam); int nScrollCode = (int) LOWORD(wParam); // scroll bar value int nPos = (short int) HIWORD(wParam); // scroll box position DoVScroll(m_hWnd, nScrollCode, nPos); } return 0; case WM_CHILDLOSTFOCUS: DoChildLostFocus(); return 0; case WM_NOTIFYSELECTIONCHANGE: return (DoNotifySelectionChange()); case WM_DISPLAYTYPELIST: DoDisplayTypeList(); return 0; case WM_COMMAND: #ifdef XP_WIN16 if (HIWORD(lParam) == EN_CHANGE) #else if (HIWORD(wParam) == EN_CHANGE) #endif { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection()); pAddress->SetExpansion(TRUE); } if (DoCommand(m_hWnd,wParam,lParam)) return 0; break; } return CListBox::DefWindowProc(message,wParam,lParam); } void CNSAddressList::EnableParsing(BOOL bParse) { m_bParse = bParse; } void CNSAddressList::SetControlParent(LPADDRESSPARENT pIAddressParent) { m_pIAddressParent = pIAddressParent; ASSERT(m_pNameField); m_pNameField->SetControlParent(pIAddressParent); } //=========================================================== ~CNSAddressList CNSAddressList::~CNSAddressList() { if (m_hTextFont) { theApp.ReleaseAppFont(m_hTextFont); } if (m_hPenNormal != NULL) ::DeleteObject((HGDIOBJ)m_hPenNormal); if (m_hPenGrid != NULL) ::DeleteObject((HGDIOBJ)m_hPenGrid); if (m_hBrushNormal != NULL) ::DeleteObject((HGDIOBJ)m_hBrushNormal); if (m_hPenGrey != NULL) ::DeleteObject((HGDIOBJ)m_hPenGrey); delete m_pAddressTypeList; delete m_pNameField; } BOOL CNSAddressList::DoCommand( HWND hwnd, WPARAM wParam, LPARAM lParam ) { #ifdef XP_WIN16 if (HIWORD(lParam) == EN_CHANGE) #else if (HIWORD(wParam) == EN_CHANGE) #endif { UpdateHeaderContents(); return TRUE; } #ifdef XP_WIN16 else if (HIWORD(lParam) == LBN_SELCHANGE) #else else if (HIWORD(wParam) == LBN_SELCHANGE) #endif { UpdateHeaderType(); return TRUE; } #ifdef XP_WIN16 else if (wParam >= IDM_HEADER && wParam <= IDM_HEADER+MAX_HEADER_ITEMS) { HeaderCommand(wParam-IDM_HEADER); return TRUE; } #else else if (!HIWORD(wParam) && // zero if from a menu. (LOWORD(wParam) >= IDM_HEADER && LOWORD(wParam) <= IDM_HEADER+MAX_HEADER_ITEMS)) { HeaderCommand(LOWORD(wParam)-IDM_HEADER); return TRUE; } #endif return FALSE; } int CNSAddressList::SetActiveSelection(int nSelect) { if (GetActiveSelection() != nSelect) return SetCurSel(nSelect); return nSelect; } BOOL CNSAddressList::Create(CWnd *pParent, int id) { RECT rect; ::GetClientRect(pParent->m_hWnd, &rect); BOOL bRetVal = CListBox::Create( WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE|WS_VSCROLL| LBS_HASSTRINGS|LBS_OWNERDRAWFIXED|LBS_NOTIFY|LBS_WANTKEYBOARDINPUT|LBS_NOINTEGRALHEIGHT, rect,pParent,id); m_bCreated = TRUE; return bRetVal; } //=============================================================== SetSel int CNSAddressList::SetSel(int nIndex, BOOL bSelect) { int result; if (bSelect) { result = SetActiveSelection(nIndex); m_pNameField->SetSel(0,-1,TRUE); } else { result = SetActiveSelection(-1); m_pNameField->SetSel(-1,0,TRUE); } Invalidate(); return result; } //=============================================================== AppendEntry int CNSAddressList::AppendEntry( NSAddressListEntry *pAddressEntry, BOOL expandName ) { SetActiveSelection(-1); return InsertEntry( (int)-1, pAddressEntry, expandName ); } //=============================================================== InsertEntry int CNSAddressList::InsertEntry( int nIndex, NSAddressListEntry *pAddressEntry, BOOL expandName ) { if (pAddressEntry && pAddressEntry->szName && strlen(pAddressEntry->szName)) { if (m_bDrawTypeList) { if (pAddressEntry->szType && strlen(pAddressEntry->szType)) { int iPos; ASSERT(m_pAddressTypeList); if ((iPos =m_pAddressTypeList->FindStringExact(-1,pAddressEntry->szType))!=LB_ERR) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(iPos); ASSERT(pInfo); if (pInfo->GetExclusive()) { CString cs; cs = pInfo->GetValue(); if (cs.GetLength()) { cs += ","; cs += pAddressEntry->szName; } else cs = pAddressEntry->szName; pInfo->SetValue(cs); } if (pInfo->GetHidden()) return LB_ERR; } } } if (GetActiveSelection()!=LB_ERR && !m_pNameField->LineLength()) { NSAddressListEntry pTemp; GetEntry(GetActiveSelection(),&pTemp); if (!pTemp.szName||!strlen(pTemp.szName)) { SetEntry(GetActiveSelection(),pAddressEntry); CRect rect; GetItemRect(m_hWnd, GetActiveSelection(),&rect); InvalidateRect(rect); m_pNameField->SetFocus(); return GetActiveSelection(); } } } CNSAddressInfo *pAddress = new CNSAddressInfo; if ( pAddressEntry == NULL) { // Default to callback provided bitmap and the first // address type in the address type list. if (m_bDrawTypeList) { CString cs; int index = GetCount(); if (index > 0 && index != LB_ERR) { CNSAddressInfo *pLastAddress = (CNSAddressInfo *)GetItemDataPtr(index-1); cs = pLastAddress->GetType(); int index = m_pAddressTypeList->FindStringExact(-1,cs); if (index != LB_ERR) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(index); ASSERT(pInfo); if (pInfo->GetExclusive()) m_pAddressTypeList->GetText(0,cs); } } else m_pAddressTypeList->GetText(0,cs); pAddress->SetType(cs); pAddress->SetBitmap(0); pAddress->SetEntryID(); pAddress->SetName(""); } } else { if (m_bDrawTypeList) { BOOL bFound = FALSE; for (int i = 0; i < m_pAddressTypeList->GetCount(); i++) { CString cs; m_pAddressTypeList->GetText(i,cs); if (cs == pAddressEntry->szType) { bFound = TRUE; m_pAddressTypeList->SetCurSel(i); break; } } if (!bFound) { delete pAddress; return (int)LB_ERR; } } pAddress->SetType(pAddressEntry->szType); pAddress->SetName(pAddressEntry->szName); pAddress->SetBitmap(pAddressEntry->idBitmap); pAddress->SetEntryID(pAddressEntry->idEntry); } int index = InsertString( nIndex, (LPCTSTR)pAddress ); if ( index < 0 ) return FALSE; SetItemDataPtr( index, pAddress ); // this ensures that there will always be a selected line if there are entries if ( (GetCount() == 1) || (GetActiveSelection() == LB_ERR) ) { SetActiveSelection( 0 ); UpdateHeaderType(); UpdateHeaderContents(); } CRect WindowRect, ItemRect; GetWindowRect(WindowRect); if (m_pIAddressParent && expandName) m_pIAddressParent->AddedItem(m_hWnd, 0, index); SetActiveSelection(index); return index; } //================================================================== SetEntry void CNSAddressList::SetCSID( int16 csid ) { if(m_hWnd) { HDC hDC = ::GetDC(m_hWnd); LOGFONT lf; memset(&lf,0,sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_MODERN | FIXED_PITCH; strcpy(lf.lfFaceName, IntlGetUIFixFaceName(csid)); lf.lfHeight = -MulDiv(NS_ADDRESSFONTSIZE,::GetDeviceCaps(hDC,LOGPIXELSY),72); lf.lfQuality = PROOF_QUALITY; lf.lfCharSet = IntlGetLfCharset(csid); m_hTextFont = theApp.CreateAppFont( lf); ::SendMessage(GetSafeHwnd(), WM_SETFONT, (WPARAM)m_hTextFont, FALSE); ::ReleaseDC(m_hWnd,hDC); } if(m_pNameField) m_pNameField->SetCSID(csid); } //================================================================== SetEntry BOOL CNSAddressList::SetEntry( int nIndex, NSAddressListEntry *pNewAddressEntry ) { // sanity checks if ( (int)nIndex >= GetCount() ) return FALSE; if (m_bDrawTypeList) if (IsWindow(m_pAddressTypeList->m_hWnd)) if ( m_pAddressTypeList->FindStringExact( -1, pNewAddressEntry->szType ) == LB_ERR ) return FALSE; // update entry CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); pAddress->SetType(pNewAddressEntry->szType); pAddress->SetName(pNewAddressEntry->szName); pAddress->SetBitmap(pNewAddressEntry->idBitmap); pAddress->SetEntryID(pNewAddressEntry->idEntry); if (m_pIAddressParent) { NSAddressListEntry entry; BOOL bRetVal = GetEntry(nIndex,&entry); if (bRetVal) { unsigned long entryID = 0; UINT bitmapID = 0; char * pszFullName = NULL; CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); if (pAddress && pAddress->GetExpansion()) { BOOL bExpand = TRUE; if (m_bDrawTypeList) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData( m_pAddressTypeList->GetCurSel()); bExpand = pInfo->GetExpand(); } if (bExpand) { m_pIAddressParent->ChangedItem((char*)entry.szName, nIndex, m_hWnd, &pszFullName, &entryID, &bitmapID); if (pszFullName != NULL) { pAddress->SetName(pszFullName); if (bitmapID) SetItemBitmap(nIndex, bitmapID); if (entryID) SetItemEntryID(nIndex, entryID); free(pszFullName); } } } } } return TRUE; } //================================================================== GetEntry BOOL CNSAddressList::GetEntry( int nIndex, NSAddressListEntry *pAddressEntry ) { if ( (int)nIndex >= GetCount() ) return FALSE; // fill out the NSAddressListEntry to return it to the caller CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); if ( pAddress == (CNSAddressInfo *)-1 || !pAddress->GetName()) return FALSE; pAddressEntry->szType = pAddress->GetType(); pAddressEntry->szName = pAddress->GetName(); pAddressEntry->idBitmap = pAddress->GetBitmap(); pAddressEntry->idEntry = pAddress->GetEntryID(); return TRUE; } BOOL CNSAddressList::RemoveSelection(int nIndex) { if (nIndex == -1) { int iSel = GetActiveSelection(); if (iSel != LB_ERR) return DeleteEntry(iSel); return FALSE; } return DeleteEntry(nIndex); } //=============================================================== DeleteEntry BOOL CNSAddressList::DeleteEntry( int nIndex ) { // sanity check if( (int)nIndex >= GetCount() ) return FALSE; if (m_bDrawTypeList) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData( m_pAddressTypeList->GetCurSel()); if (pInfo) { if (pInfo->GetExclusive()) pInfo->SetValue(NULL); } } if (GetCount() == 1) { m_pNameField->SetWindowText(""); UpdateHeaderContents(); if (m_pIAddressParent) m_pIAddressParent->DeletedItem(m_hWnd, 0, nIndex); return FALSE; } // handle selection if deleting selected address if ( (int)nIndex == GetActiveSelection() ) { // delete only entry? if ( GetCount() == 1 ) { if (m_bDrawTypeList) m_pAddressTypeList->ShowWindow( SW_HIDE ); m_pNameField->ShowWindow( SW_HIDE ); } else if ( nIndex > 0 ) { SetActiveSelection(nIndex-1); } } // delete this entry if ( DeleteString( nIndex ) == LB_ERR ) return FALSE; if (m_pIAddressParent) m_pIAddressParent->DeletedItem(m_hWnd, 0, nIndex); return TRUE; } //================================================================= FindEntry int CNSAddressList::FindEntry( int nStart, LPCTSTR lpszName ) { CNSAddressInfo *pAddress; if ( nStart == (int)-1 ) nStart = 0; for ( int i = nStart; i < GetCount(); i++ ) { pAddress = (CNSAddressInfo *)GetItemDataPtr(i); if (pAddress->GetName()) if ( strcmp( pAddress->GetName(), lpszName ) == 0 ) return i; } return (int)LB_ERR; } BOOL CNSAddressList::AddAddressType( char * pszChoice, UINT pidBitmap, BOOL bExpand, BOOL bHidden, BOOL bExclusive, DWORD dwUserData) { // Create the ComboBox if necessary if (pszChoice != NULL) { if ( !IsWindow( m_pAddressTypeList->m_hWnd ) ) VERIFY( m_pAddressTypeList->Create( this ) ); // create the edit field if necessary int position = m_pAddressTypeList->InsertString( -1, pszChoice ); if (position == LB_ERR) return FALSE; CNSAddressTypeInfo * pInfo = new CNSAddressTypeInfo(pidBitmap,bHidden,bExclusive,dwUserData,bExpand); if (pInfo == NULL) return FALSE; m_pAddressTypeList->SetItemData(position,(DWORD)pInfo); m_bDrawTypeList = TRUE; if (m_pAddressTypeList->GetCurSel()==LB_ERR) m_pAddressTypeList->SetCurSel(0); } if ( !IsWindow( m_pNameField->m_hWnd ) ) VERIFY( m_pNameField->Create( this ) ); return TRUE; } //==================================================== GetAddressTypeComboBox CListBox * CNSAddressList::GetAddressTypeComboBox( void ) { // Create the ComboBox if necessary if ( !IsWindow( m_pAddressTypeList->m_hWnd ) ) VERIFY( m_pAddressTypeList->Create( this ) ); return (CListBox*)m_pAddressTypeList; } //======================================================= GetAddressNameField CEdit * CNSAddressList::GetAddressNameField( void ) { return m_pNameField; } //=========================================================== EnableGridLines void CNSAddressList::EnableGridLines( BOOL bEnable ) { if ( m_bGridLines == bEnable ) return; m_bGridLines = bEnable; // redraw the control using the new grid-lines setting Invalidate( TRUE ); } int CNSAddressList::GetItemFromPoint(LPPOINT lpPoint) { BOOL bOutside; return ItemFromPoint(m_hWnd,lpPoint,&bOutside); } ///////////////////////////////////////////////////////////////////////////// // CNSAddressList private API UINT CNSAddressList::ItemFromPoint(HWND hwnd, LPPOINT lpPoint, BOOL * bOutside) const { RECT rect; ::GetClientRect(hwnd, &rect); int iHeight = (int)::SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); int iCount = (int)::SendMessage(hwnd, LB_GETCOUNT, 0, 0); int iTopIndex = (int)::SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); int iListHeight = iHeight * ( iCount - iTopIndex ); rect.bottom = rect.bottom < iListHeight ? rect.bottom : iListHeight; *bOutside = !::PtInRect(&rect, *lpPoint); if ( *bOutside ) { return 0; } return (lpPoint->y / iHeight) + iTopIndex; } //================================================================ OnKeyPress BOOL CNSAddressList::OnKeyPress( CWnd *pChildControl, UINT nKey, UINT nRepCnt, UINT nFlags ) { switch (nKey) { case VK_HOME: if (GetActiveSelection()) SetActiveSelection(0); else if (m_bDrawTypeList) m_pAddressTypeList->SetFocus(); break; case VK_END: if (GetActiveSelection() != (GetCount()-1)) SetActiveSelection(GetCount()-1); else m_pNameField->SetFocus(); break; case VK_UP: if (GetActiveSelection()) SetActiveSelection(GetActiveSelection()-1); break; case VK_DOWN: if (GetActiveSelection()LineLength(); if (nKey == VK_DELETE) { if (nSelect >= GetCount()) nSelect = GetCount()-1; SetActiveSelection(nSelect); Invalidate(); } else m_pNameField->SetSel(iLineLength,iLineLength,TRUE); return TRUE; } break; case VK_BACK: if (!m_pNameField->LineLength()) { if (GetCount()>1 && GetActiveSelection()) { DeleteEntry(GetActiveSelection()); if (GetActiveSelection()==LB_ERR) SetActiveSelection(0); UpdateWindow(); int iLineLength = m_pNameField->LineLength(); m_pNameField->SetSel(iLineLength,iLineLength,TRUE); } else return FALSE; return TRUE; } break; case VK_RETURN: if (DoNotifySelectionChange() != -1) { if ((GetActiveSelection()+1 == GetCount())) { // don't add a second blank line if ( m_pNameField->LineLength() == 0 ) { CWnd *pNextWnd = GetNextWindow(GW_HWNDNEXT); if (pNextWnd) pNextWnd->SetFocus(); else GetParent()->SendMessage(WM_LEAVINGLASTFIELD); return TRUE; } // add the new address entry to the list InsertEntry( GetActiveSelection()+1,NULL); // select the new address and make sure its visible SetActiveSelection( GetActiveSelection()+1 ); return TRUE; } else { SetActiveSelection( GetActiveSelection()+1 ); } return TRUE; } else SetSel( GetActiveSelection(), TRUE); return TRUE; break; } if (nKey == VK_TAB) { if (DoNotifySelectionChange() != -1) { BOOL bShift = GetKeyState( VK_SHIFT ) & 0x8000; if ( !bShift && (pChildControl->m_hWnd == m_pAddressTypeList->m_hWnd) ) m_pNameField->SetFocus(); else if ( m_bDrawTypeList && bShift && (pChildControl->m_hWnd == m_pNameField->m_hWnd) ) m_pAddressTypeList->SetFocus(); else if ( !bShift && (GetActiveSelection()+1 == GetCount()) ) { CWnd *pNextWnd = GetNextWindow(GW_HWNDNEXT); if (pNextWnd) pNextWnd->SetFocus(); else GetParent()->SendMessage(WM_LEAVINGLASTFIELD); } else if ( bShift && (GetActiveSelection() == 0) ) // first line { CWnd *pNextWnd = GetNextWindow( GW_HWNDPREV ); if (pNextWnd) pNextWnd->SetFocus(); } else // middle line { // select the next or previous line in the address list if ( bShift ) { SetActiveSelection( GetActiveSelection()-1 ); m_pNameField->SetFocus(); } else { SetActiveSelection( GetActiveSelection()+1 ); if (m_bDrawTypeList) m_pAddressTypeList->SetFocus(); } } } else SetSel( GetActiveSelection(), TRUE); return TRUE; } return FALSE; // not handled - let the child continue processing this key } void CNSAddressList::DrawEntryBitmap( int iSel, CNSAddressInfo * pAddress, CDC * pDC, BOOL bErase ) { CRect rect; if (GetItemRect(m_hWnd,iSel,rect)!=LB_ERR) { CRect rectBitmap( m_iFieldControlWidth, rect.top, m_iFieldControlWidth + m_iBitmapWidth, rect.bottom ); if (!m_bDrawTypeList) { rectBitmap.left = rect.left; rectBitmap.right = rect.left + m_iBitmapWidth; } int iBitmap = pAddress->GetBitmap(); if (!iBitmap) iBitmap = GetDefaultBitmapId(); if (iBitmap) { if (bErase) NS_FillSolidRect(pDC->GetSafeHdc(),rectBitmap,GetSysColor(COLOR_WINDOW)); BITMAP bitmap; CBitmap cbitmap; cbitmap.LoadBitmap(MAKEINTRESOURCE(iBitmap)); cbitmap.GetObject(sizeof(BITMAP),&bitmap); int center_x = rectBitmap.left + (rectBitmap.Width() - bitmap.bmWidth)/2; int center_y = rectBitmap.top + (rectBitmap.Height()-bitmap.bmHeight)/2; DrawTransparentBitmap( pDC->GetSafeHdc(), (HBITMAP)cbitmap.GetSafeHandle(), center_x, center_y, RGB(255,0,255)); cbitmap.DeleteObject(); } } } void CNSAddressList::UpdateHeaderType(void) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection()); if (pAddress != (CNSAddressInfo *)-1 && IsWindow(m_pAddressTypeList->m_hWnd) && m_bDrawTypeList) { CString cs; m_pAddressTypeList->GetText(m_pAddressTypeList->GetCurSel(),cs); if (strcmp(pAddress->GetType(),cs)) { pAddress->SetType(cs); int iSel = m_pAddressTypeList->GetCurSel(); if (iSel != -1) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(iSel); ASSERT(pInfo!=(CNSAddressTypeInfo*)-1); UINT idBitmap = pInfo->GetBitmap(); pAddress->SetBitmap(idBitmap); CRect rect; CDC * pDC = GetDC(); DrawEntryBitmap(GetActiveSelection(), pAddress, pDC, TRUE); ReleaseDC(pDC); } } GetTypeFieldLength(); } } int CNSAddressList::GetTypeFieldLength() { CString cs = ""; char * pszString; HDC hDC = ::GetDC(m_hWnd); HGDIOBJ hOldFont = ::SelectObject(hDC, (HFONT) ::SendMessage(m_pAddressTypeList->GetSafeHwnd(), WM_GETFONT, 0 ,0)); int iMaxLength = 0; SIZE ptSize; for (int i =0; iGetType(); ::GetTextExtentPoint(hDC,pszString,strlen(pszString),&ptSize); int iTemp = ptSize.cx + (TEXT_PAD * 2) + m_iTypeBitmapWidth; if (iTemp > iMaxLength) iMaxLength = iTemp; } pszString = "A&"; ::GetTextExtentPoint(hDC,pszString,strlen(pszString),&ptSize); iMaxLength -= ptSize.cx; ::SelectObject(hDC,hOldFont); ::ReleaseDC(m_hWnd,hDC); if (iMaxLength != m_iFieldControlWidth) { m_iFieldControlWidth = iMaxLength; ::InvalidateRect(m_hWnd,NULL,TRUE); ::UpdateWindow(m_hWnd); } return iMaxLength; } void CNSAddressList::UpdateHeaderContents(void) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection()); if (pAddress != (CNSAddressInfo *)-1) { CString cs; m_pNameField->GetWindowText(cs); pAddress->SetName(cs); if (m_bDrawTypeList) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(m_pAddressTypeList->GetCurSel()); if (pInfo != (CNSAddressTypeInfo*)-1) { if (pInfo->GetExclusive()) pInfo->SetValue(cs); } } } } void CNSAddressList::HeaderCommand(int nID) { if (GetActiveSelection()!=LB_ERR && m_bDrawTypeList) { m_pAddressTypeList->SetCurSel(nID); UpdateHeaderType(); m_pNameField->SetFocus(); CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(nID); ASSERT(pInfo); if (pInfo->GetExclusive()) { CString cs; m_pNameField->GetWindowText(cs); if (!cs.GetLength()) m_pNameField->SetWindowText(pInfo->GetValue()); pInfo->SetHidden(FALSE); pInfo->SetExclusive(FALSE); UpdateHeaderContents(); int iLineLength = m_pNameField->LineLength(); UpdateWindow(); m_pNameField->SetSel(iLineLength,iLineLength,TRUE); } else { CString cs; m_pAddressTypeList->GetText (nID, cs); if (!strnicmp(cs,szLoadString(IDS_ADDRESSREPLYTO),strlen(szLoadString(IDS_ADDRESSREPLYTO)))) pInfo->SetExclusive(TRUE); else if (!strnicmp(cs,szLoadString(IDS_ADDRESSFOLLOWUPTO), strlen(szLoadString(IDS_ADDRESSFOLLOWUPTO)))) pInfo->SetExclusive(TRUE); } } } void CNSAddressList::DoSetFocus(HWND hwnd) { if ( (GetCount() > 0) && (GetActiveSelection() != LB_ERR) ) { if (m_bDrawTypeList) ::ShowWindow(m_pAddressTypeList->m_hWnd, SW_SHOW); m_pNameField->ShowWindow( SW_SHOW ); if ( GetActiveSelection() == GetCount()-1 ) ::SetFocus(m_pNameField->m_hWnd); else if (m_bDrawTypeList) ::SetFocus(m_pAddressTypeList->m_hWnd); } } void CNSAddressList::DoKillFocus(HWND hNewWnd) { if (::GetFocus() == m_pAddressTypeList->m_hWnd || ::GetFocus() == m_pNameField->m_hWnd || ::GetFocus() == m_hWnd ) { // focus is going to one the child controls return; } if (m_bDrawTypeList) ::ShowWindow(m_pAddressTypeList->m_hWnd,SW_HIDE); if (IsWindow(m_pNameField->m_hWnd)) ::ShowWindow(m_pNameField->m_hWnd,SW_HIDE); } ///////////////////////////////////////////////////////////////////////////// // CNSAddressList virtual functions (overrides) void CNSAddressList::DrawGridLine(CRect &rect, CDC * pDC) { HDC hdc = pDC->GetSafeHdc(); HPEN hOldPen = (HPEN)::SelectObject(hdc,(HGDIOBJ)m_hPenGrey); ::MoveToEx(hdc, rect.left + m_iFieldControlWidth, rect.bottom-1, NULL); ::LineTo(hdc, rect.right, rect.bottom-1); ::SelectObject(hdc,(HGDIOBJ)hOldPen); } void CNSAddressList::ComputeFieldWidths(CDC * pDC) { if (m_bDrawTypeList) { m_iFieldControlWidth = 0; CBitmap cbitmap; cbitmap.LoadBitmap(IDB_ARROW3D); BITMAP bitmap; cbitmap.GetObject(sizeof(BITMAP), &bitmap ); m_iTypeBitmapWidth = bitmap.bmWidth; cbitmap.DeleteObject(); } m_iBitmapWidth = 24; } //=============================================================== DrawAddress void CNSAddressList::DrawAddress( int nIndex, CRect &rect, CDC *pDC, BOOL bSelected ) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(nIndex); if (!pAddress) return; if (!m_iFieldControlWidth) ComputeFieldWidths(pDC); // create CRects for each of the fields CRect rectType( rect.left, rect.top, m_iFieldControlWidth, rect.bottom ); CRect rectAddress( (m_bDrawTypeList ? rectType.right : rect.left) + m_iBitmapWidth, rect.top, rect.right, rect.bottom ); // end CRects // shrink the rectangle so that the controls draw within the grid rectAddress.bottom--; // If the bitmap is not provided, ask for it if( pAddress->GetBitmap() == NULL && m_bDrawTypeList ) { // send notification to parent int position = m_pAddressTypeList->FindString(-1,pAddress->GetType()); if (position != LB_ERR) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(position); ASSERT(pInfo); pAddress->SetBitmap(pInfo->GetBitmap()); } } int oldLine = m_lastIndex; int ioffset = ((rectAddress.Height()-m_pNameField->m_iTextHeight)+1)/2; int iremain = ((rectAddress.Height()-m_pNameField->m_iTextHeight)+1)%2; rectAddress.top += (ioffset+iremain); rectAddress.bottom -= ioffset; // draw the address type and address name fields if ( bSelected ) { if (m_bDrawTypeList) { // set the combobox m_pAddressTypeList->MoveWindow( rectType, FALSE ); m_pAddressTypeList->SelectString(-1, pAddress->GetType()); CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData( m_pAddressTypeList->GetCurSel()); m_pNameField->SetNameCompletionFlag(pInfo->GetExpand()); } int nStart, nEnd; m_pNameField->GetSel(nStart,nEnd); m_pNameField->SetWindowText(pAddress->GetName()); m_pNameField->MoveWindow( rectAddress, FALSE ); m_pNameField->UpdateWindow(); m_lastIndex = nIndex; m_pNameField->SetSel(nStart,nEnd); } if (!bSelected || !m_pNameField->IsWindowVisible()) { COLORREF cText = pDC->SetTextColor( GetSysColor( COLOR_WINDOWTEXT ) ); int iMode = pDC->SetBkMode( TRANSPARENT ); // draw the address pDC->DrawText( pAddress->GetName() ? pAddress->GetName() : "", -1, rectAddress, DT_LEFT | DT_BOTTOM | DT_NOPREFIX ); pDC->SetTextColor(cText); pDC->SetBkMode(iMode); if (m_bDrawTypeList) m_pAddressTypeList->DrawItemSoItLooksLikeAButton( pDC,rectType,CString(pAddress->GetType() ? pAddress->GetType():"")); } // end fields // draw the bitmap DrawEntryBitmap(nIndex,pAddress,pDC, (GetCurSel()==(int)nIndex)?TRUE:FALSE); HDC hdc = pDC->GetSafeHdc(); if (GetCurSel()==(int)nIndex) { HPEN hOldPen = (HPEN)::SelectObject(hdc, m_hPenNormal); if (GetCurSel()==GetTopIndex()) { ::MoveToEx(hdc,m_iFieldControlWidth,rect.top, NULL); ::LineTo(hdc,rect.right,rect.top); } ::MoveToEx(hdc,m_iFieldControlWidth,rect.bottom-1, NULL); ::LineTo(hdc,rect.right,rect.bottom-1); ::SelectObject(hdc,(HGDIOBJ)hOldPen); } DrawGridLine(rect, pDC); ValidateRect(&rect); // draw the last line if (m_lastIndex != oldLine) { CRect badRect(0, 0, 0, 0); GetItemRect(m_hWnd,oldLine,badRect); InvalidateRect(badRect); } } //================================================================== DrawItem void CNSAddressList::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct ) { if (lpDrawItemStruct->itemID != -1) { CRect rect(lpDrawItemStruct->rcItem); if (!m_iItemHeight) m_iItemHeight = rect.Height(); CDC dc; dc.Attach(lpDrawItemStruct->hDC); DrawAddress( lpDrawItemStruct->itemID, rect,&dc, (int)lpDrawItemStruct->itemID == GetActiveSelection()); dc.Detach(); } } //=============================================================== MeasureItem void CNSAddressList::MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct ) { static int iHeight = 0; if (!iHeight) { CDC * pdc = GetDC(); TEXTMETRIC tm; pdc->GetTextMetrics(&tm); iHeight = tm.tmHeight; ReleaseDC(pdc); } lpMeasureItemStruct->itemHeight = iHeight + 1; } //================================================================ DeleteItem void CNSAddressList::DeleteItem( LPDELETEITEMSTRUCT lpDeleteItemStruct ) { delete (CNSAddressInfo *)GetItemDataPtr( lpDeleteItemStruct->itemID ); } void CNSAddressList::DisplayTypeList(int item) { CRect rect; if (item == -1) item = GetActiveSelection(); CMenu cmenu; if (cmenu.CreatePopupMenu()) { for (int i = 0; i < m_pAddressTypeList->GetCount(); i++) { CString cs; m_pAddressTypeList->GetText(i,cs); cmenu.AppendMenu(MF_STRING, IDM_HEADER+i, cs.Right(cs.GetLength()-1)); } GetItemRect(m_hWnd,item,rect); CPoint pt(rect.left + m_iTypeBitmapWidth,rect.bottom); ClientToScreen(&pt); pt.y -= 2; cmenu.TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, this); } } int CNSAddressList::GetItemRect(HWND hwnd, int nIndex, LPRECT lpRect) const { ASSERT(::IsWindow(hwnd)); return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect); } //=============================================================== OnLButtonDown void CNSAddressList::DoLButtonDown(HWND hwnd, UINT nFlags, LPPOINT lpPoint) { if (m_bDrawTypeList) { BOOL bOutside; int nNewSelect = ItemFromPoint(hwnd, lpPoint, &bOutside ); RECT rect; GetItemRect(m_hWnd,nNewSelect,&rect); int iHeight = rect.bottom - rect.top; if (((lpPoint->y+iHeight)/iHeight)+GetTopIndex()>GetCount()) { if (GetCount()) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetCount()-1); if (!pAddress->GetName()||!strlen(pAddress->GetName())) { SetActiveSelection(GetCount()-1); ::SetFocus(m_pNameField->m_hWnd); return; } } AppendEntry(); ::SetFocus(m_pNameField->m_hWnd); return; } SetActiveSelection(nNewSelect); rect.right = m_iFieldControlWidth; if ((lpPoint->x >= rect.left) && (lpPoint->x <= rect.right) && (lpPoint->y >= rect.top) && (lpPoint->y <= rect.bottom)) { m_bArrowDown = TRUE; DisplayTypeList(nNewSelect); } else if (lpPoint->x < m_iFieldControlWidth) ::SetFocus(m_pAddressTypeList->m_hWnd); else ::SetFocus(m_pNameField->m_hWnd); } } void CNSAddressList::DoLButtonUp(HWND hwnd, UINT nFlags, LPPOINT lpPoint) { BOOL bOutside; int nNewSelect = ItemFromPoint(hwnd, lpPoint, &bOutside ); if ( bOutside ) return; if (m_bArrowDown) { m_bArrowDown = FALSE; } else { // set the selection if ( nNewSelect != GetActiveSelection() ) { SetActiveSelection( nNewSelect ); } // set the focus if (lpPoint->x <= m_iFieldControlWidth) ::SetFocus(m_pAddressTypeList->m_hWnd); else ::SetFocus(m_pNameField->m_hWnd); } } void CNSAddressList::DoVScroll(HWND hwnd, UINT nSBCode, UINT nPos) { ::SetScrollPos(hwnd, SB_VERT, GetTopIndex(), TRUE); } //========================================================== OnChildLostFocus // This method is called when one of the child control looses // focus without preparation (ie no Tab or Enter). void CNSAddressList::DoChildLostFocus() { if (DoNotifySelectionChange() != -1) DoKillFocus(NULL); } BOOL CNSAddressList::ParseAddressEntry(int nSelection) { if (!m_bParse) return FALSE; NSAddressListEntry entry; if (GetEntry(nSelection, &entry)) { int iCount; char * pNames = NULL, * pAddresses = NULL; if (!entry.szName || XP_STRLEN (entry.szName) == 0) return FALSE; char * pName = m_pIAddressParent->NameCompletion((char *)entry.szName); if (pName) { free(pName); return FALSE; } iCount = MSG_ParseRFC822Addresses(entry.szName, &pNames, &pAddresses); if (iCount > 1) { char * p1, * p2; char *pLastType = NULL; BOOL bExpanded = FALSE; p1 = pNames; p2 = pAddresses; LockWindowUpdate(); for (int i = 0; iGetItemData( m_pAddressTypeList->GetCurSel()); bExpand = pInfo->GetExpand(); } if (bExpand) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection()); if (pAddress && pAddress->GetExpansion()) { result = m_pIAddressParent->ChangedItem( (char*)entry.szName,GetActiveSelection(),m_hWnd, &pszFullName, &entryID, &bitmapID); if (pszFullName != NULL) { pAddress->SetName(pszFullName); if (bitmapID) SetItemBitmap(GetActiveSelection(), bitmapID); if (entryID) SetItemEntryID(GetActiveSelection(), entryID); free(pszFullName); } } } } Invalidate(); } } return result; } void CNSAddressList::DoDisplayTypeList() { DisplayTypeList(); } void CNSAddressList::SetItemName(int nIndex, char * text) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); pAddress->SetName(text); } void CNSAddressList::SetItemBitmap(int nIndex, UINT id) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); pAddress->SetBitmap(id); CRect rect; GetItemRect(m_hWnd,nIndex,rect); } void CNSAddressList::SetItemEntryID(int nIndex, unsigned long id) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); pAddress->SetEntryID(id); CRect rect; GetItemRect(m_hWnd,nIndex,rect); } BOOL CNSAddressList::DoEraseBkgnd(HWND hwnd, HDC hdc) { RECT rect; ::GetClientRect(hwnd,&rect); if (!m_iItemHeight) m_iItemHeight = GetItemHeight(0); int iGridLines = (rect.bottom-rect.top)/m_iItemHeight; HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc,(HGDIOBJ)m_hBrushNormal); HPEN hOldPen = (HPEN)::SelectObject(hdc,(HGDIOBJ)m_hPenNormal); int iTotal = GetCount() - GetTopIndex(); for (int i = 0; i <= iGridLines; i++) { CRect GridRect( rect.left,rect.top+(i*m_iItemHeight), rect.right,rect.top + ((i+1)*m_iItemHeight) - 1); GridRect.top--; if (i < iTotal) GridRect.left = m_iFieldControlWidth; GridRect.top++; NS_FillSolidRect(hdc,GridRect,GetSysColor(COLOR_WINDOW)); GridRect.top--; ::SelectObject(hdc,(HGDIOBJ)m_hPenGrid); ::MoveToEx(hdc,GridRect.left, GridRect.bottom , NULL); ::LineTo(hdc,GridRect.right, GridRect.bottom ); if (m_bDrawTypeList && m_pAddressTypeList->GetCount() && (i >= iTotal)) { ::MoveToEx(hdc,GridRect.left+m_iFieldControlWidth,GridRect.top, NULL); ::LineTo(hdc,GridRect.left+m_iFieldControlWidth,GridRect.bottom ); } ::SelectObject(hdc,(HGDIOBJ)m_hPenNormal); } ::SelectObject(hdc,(HGDIOBJ)hOldPen); ::SelectObject(hdc,(HGDIOBJ)hOldBrush); return TRUE; } int CNSAddressList::SetAddressList ( LPNSADDRESSLIST pAddressList, int count ) { ResetContent(); if (pAddressList) { for (int index = 0; index < count; index++) { NSAddressListEntry address; address.szType = MSG_HeaderMaskToString(pAddressList[index].ulHeaderType); address.idBitmap = pAddressList[index].idBitmap; address.idEntry = pAddressList[index].idEntry; if (pAddressList[index].szAddress) { address.szName = strdup (pAddressList[index].szAddress); free (pAddressList[index].szAddress); } AppendEntry(&address); } free(pAddressList); } return count; } int CNSAddressList::AppendEntry( BOOL expandName, LPCTSTR szType, LPCTSTR szName, UINT idBitmap, unsigned long idEntry) { if (!szType && !szName && !idBitmap && !idEntry) return AppendEntry(); NSAddressListEntry address; address.szType = szType; address.szName = szName; address.idBitmap = idBitmap; address.idEntry = idEntry; return AppendEntry(&address, expandName); } int CNSAddressList::InsertEntry( int nIndex, BOOL expandName, LPCTSTR szType, LPCTSTR szName, UINT idBitmap, unsigned long idEntry) { if (!szType && !szName && !idBitmap && !idEntry) return InsertEntry(nIndex,NULL); NSAddressListEntry address; address.szType = szType; address.szName = szName; address.idBitmap = idBitmap; address.idEntry = idEntry; return InsertEntry(nIndex,&address, expandName); } BOOL CNSAddressList::SetEntry( int nIndex, LPCTSTR szType, LPCTSTR szName, UINT idBitmap, unsigned long idEntry) { NSAddressListEntry address; address.szType = szType; address.szName = szName; address.idBitmap = idBitmap; address.idEntry = idEntry; return SetEntry(nIndex,&address); } #pragma optimize void CNSAddressList::GetTypeInfo( int nIndex, ADDRESS_TYPE_FLAG flag, void ** pData) { CListBox * pTypeList = GetAddressTypeComboBox(); CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)pTypeList->GetItemData(nIndex); ASSERT(pData); *pData = NULL; if (flag & ADDRESS_TYPE_FLAG_VALUE) *pData = (void*)pInfo->GetValue(); else if (flag & ADDRESS_TYPE_FLAG_HIDDEN) *pData = (void*)pInfo->GetHidden(); else if (flag & ADDRESS_TYPE_FLAG_EXCLUSIVE) *pData = (void*)pInfo->GetExclusive(); else if (flag & ADDRESS_TYPE_FLAG_USER) *pData = (void*)pInfo->GetUserData(); else if (flag & ADDRESS_TYPE_FLAG_BITMAP) *pData = (void*)pInfo->GetBitmap(); } BOOL CNSAddressList::GetEntry( int nIndex, char **szType, char **szName, UINT *idBitmap, unsigned long *idEntry) { NSAddressListEntry address; BOOL bRetVal = GetEntry(nIndex,&address); if (bRetVal) { if (szType) *szType = (char*)address.szType; if (szName) *szName = (char*)address.szName; if (idBitmap) *idBitmap = address.idBitmap; if (idEntry) *idEntry = address.idEntry; } return bRetVal; } int CNSAddressList::GetAddressList ( LPNSADDRESSLIST * ppAddressList ) { int count = GetCount(); if (count) { *ppAddressList = (LPNSADDRESSLIST)calloc(count,sizeof(NSADDRESSLIST)); if (*ppAddressList) { for (int index = 0; index < count; index++) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( index ); ASSERT(pAddress); if (pAddress->GetType()) (*ppAddressList)[index].ulHeaderType = MSG_StringToHeaderMask(pAddress->GetType()); if (pAddress->GetName()) (*ppAddressList)[index].szAddress = strdup(pAddress->GetName()); (*ppAddressList)[index].idEntry = pAddress->GetEntryID(); (*ppAddressList)[index].idBitmap = pAddress->GetBitmap(); } } } return count; } STDMETHODIMP CNSAddressList::QueryInterface( REFIID refiid, LPVOID * ppv) { *ppv = NULL; if (IsEqualIID(refiid,IID_IAddressControl)) *ppv = (LPADDRESSCONTROL) this; if (*ppv != NULL) { AddRef(); return NOERROR; } return CGenericObject::QueryInterface(refiid,ppv); } STDMETHODIMP_(ULONG) CNSAddressList::Release(void) { ULONG ulRef; ulRef = --m_ulRefCount; if (m_ulRefCount == 0) { LPAPIAPI pApiapi = GetAPIAPI(); pApiapi->RemoveInstance(this); delete this; } return ulRef; } // Address Control Factory //////////////////////////////////////////////////////////////////////////////////////// class CNSAddressControlFactory : public CGenericFactory { public: CNSAddressControlFactory(); ~CNSAddressControlFactory(); STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter,REFIID refiid, LPVOID * ppvObj); }; CNSAddressControlFactory::CNSAddressControlFactory() { ApiApiPtr(api); api->RegisterClassFactory(APICLASS_ADDRESSCONTROL,this); } CNSAddressControlFactory::~CNSAddressControlFactory() { } STDMETHODIMP CNSAddressControlFactory::CreateInstance( LPUNKNOWN pUnkOuter, REFIID refiid, LPVOID * ppvObj) { CNSAddressList * pAddressControl = new CNSAddressList; *ppvObj = (LPVOID)((LPUNKNOWN)pAddressControl); return NOERROR; } static void FillSolidRect(HDC hdc, LPCRECT lpRect, COLORREF clr) { ::SetBkColor(hdc, clr); ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL); } static void FillSolidRect(HDC hdc, int x, int y, int cx, int cy, COLORREF clr) { ::SetBkColor(hdc, clr); RECT rect; rect.left = x; rect.top = y; rect.right = x + cx; rect.bottom = y + cy; ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); } static void Draw3dRect(HDC hdc, int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight) { FillSolidRect(hdc, x, y, cx - 1, 1, clrTopLeft); FillSolidRect(hdc, x, y, 1, cy - 1, clrTopLeft); FillSolidRect(hdc, x + cx, y, -1, cy, clrBottomRight); FillSolidRect(hdc, x, y + cy, cx, -1, clrBottomRight); } static void Draw3dRect(HDC hdc, LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight) { Draw3dRect(hdc, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight); } void NS_FillSolidRect(HDC hdc, LPCRECT crRect, COLORREF rgbFill) { FillSolidRect(hdc,crRect, rgbFill); } void NS_Draw3dRect(HDC hdc, LPCRECT crRect, COLORREF rgbTL, COLORREF rgbBR) { #ifdef XP_WIN32 Draw3dRect(hdc, crRect, rgbTL, rgbBR); #else CRect crMunge = crRect; crMunge.right -= 1; crMunge.bottom = crMunge.top + 1; NS_FillSolidRect(hdc, crMunge, rgbTL); crMunge = crRect; crMunge.right = crMunge.left + 1; crMunge.bottom -= 1; NS_FillSolidRect(hdc, crMunge, rgbTL); crMunge = crRect; crMunge.left += crMunge.right; crMunge.right -= 1; NS_FillSolidRect(hdc, crMunge, rgbBR); crMunge = crRect; crMunge.top = crMunge.bottom; crMunge.bottom -= 1; NS_FillSolidRect(hdc, crMunge, rgbBR); #endif } //============================================================= DrawHighlight // Draw the highlight around the area static void DrawHighlight( HDC hDC, LPRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight ) { HPEN hpenTopLeft = ::CreatePen( PS_SOLID, 0, clrTopLeft ); HPEN hpenBottomRight = ::CreatePen( PS_SOLID, 0, clrBottomRight ); HPEN hpenOld = (HPEN) ::SelectObject( hDC, hpenTopLeft ); ::MoveToEx( hDC, lpRect->left, lpRect->bottom, NULL ); ::LineTo( hDC, lpRect->left, lpRect->top ); ::LineTo( hDC, lpRect->right - 1, lpRect->top ); ::SelectObject( hDC, hpenBottomRight ); ::LineTo( hDC, lpRect->right - 1, lpRect->bottom - 1); ::LineTo( hDC, lpRect->left, lpRect->bottom - 1); ::SelectObject( hDC, hpenOld ); VERIFY(::DeleteObject( hpenTopLeft )); VERIFY(::DeleteObject( hpenBottomRight )); } //============================================================ DrawRaisedRect void NS_DrawRaisedRect( HDC hDC, LPRECT lpRect ) { RECT rcTmp = *lpRect; ::InflateRect( &rcTmp, -1, -1 ); #ifdef _WIN32 DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_3DLIGHT ), GetSysColor( COLOR_3DSHADOW ) ); DrawHighlight( hDC, lpRect, GetSysColor( COLOR_3DHILIGHT ), GetSysColor( COLOR_3DDKSHADOW ) ); #else DrawHighlight( hDC, lpRect, GetSysColor( COLOR_BTNHIGHLIGHT ), GetSysColor( COLOR_BTNSHADOW ) ); DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_BTNHIGHLIGHT ), GetSysColor( COLOR_BTNSHADOW ) ); #endif } //=========================================================== DrawLoweredRect void NS_DrawLoweredRect( HDC hDC, LPRECT lpRect ) { RECT rcTmp = *lpRect; ::InflateRect( &rcTmp, -1, -1 ); #ifdef _WIN32 DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_3DSHADOW ), GetSysColor( COLOR_3DLIGHT ) ); DrawHighlight( hDC, lpRect, GetSysColor( COLOR_3DDKSHADOW ), GetSysColor( COLOR_3DHILIGHT) ); #else DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_BTNSHADOW ), GetSysColor( COLOR_BTNHIGHLIGHT ) ); DrawHighlight( hDC, lpRect, GetSysColor( COLOR_BTNSHADOW ), GetSysColor( COLOR_BTNHIGHLIGHT ) ); #endif } void NS_Draw3DButtonRect( HDC hDC, LPRECT lpRect, BOOL bPushed ) { if ( bPushed ) { NS_DrawLoweredRect( hDC, lpRect ); } else { NS_DrawRaisedRect( hDC, lpRect ); } } #if defined(__APIAPIDLL) __declspec( dllexport ) int ApiBooter(char * pszClassName) { if (!stricmp(pszClassName,APICLASS_ADDRESSCONTROL)) new CNSAddressControlFactory; return 1; } #else DECLARE_FACTORY(CNSAddressControlFactory); #endif // Address Control Object