Click here to Skip to main content
15,885,903 members
Articles / Programming Languages / C++

The Windows Access Control Model Part 4

Rate me:
Please Sign up or sign in to vote.
4.86/5 (29 votes)
7 Sep 200543 min read 228.2K   6.8K   100  
The final article in the access control series presents a guide to the access control editor and its associated ISecurityInformation interface.
/**
*	This code is by OShah. all code will have the following licence.
*	Copyright Shexec32. All code bears the following licence:
**/

/**
*	Copyright Shexec32 2004-2005. All rights reserved.
*
*	THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
*	ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
*	TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
*	PARTICULAR PURPOSE.
**/



/** This file is the URL control presented at www.catch22.net that
*	turns a static text label into a url link. The code has been
*	slightly altered to work with FilePermsBox. The code is apparently
*	public domain and comes with the following introductory notice:
*
*	urlctrl - altered static text ctrl - bittmann 2004
*
*  based upon "urlctrl" by jbrown
*  please visit: http://www.catch22.net/tuts/
**/

#include "SecurityCore.h"
#include "UrlCtrl.h"

typedef struct tagURLCTRL
{
	sized_array<TCHAR> szURL;//url!=display
	WNDPROC oldproc;//old window proc
	HCURSOR hcur;//cursor
	HFONT hfont;//underlined font
	COLORREF crUnvisited;//color unvisited
	COLORREF crVisited;//color visited
	BOOL fClicking;//internal state
	DWORD dwFlags;//combination of UCF_xxx values
} URLCTRL;


BOOL util_url_draw(HWND, HDC, RECT*); //draw (LPRECT==NULL) OR calc (LPRECT!=NULL)
BOOL util_url_fit(HWND, BOOL); //resize window
BOOL util_url_open(HWND );//open url
LRESULT CALLBACK urlctrl_proc(HWND, UINT, WPARAM, LPARAM);




BOOL util_url_draw(HWND hwnd,HDC hdc,RECT *calcrect)
{/* calc OR draw */
	if(::GetWindowLongPtr(hwnd, GWLP_WNDPROC) == reinterpret_cast<LONG_PTR>(urlctrl_proc) && hdc)
	{/* is urlctrl and hdc? */
		URLCTRL *url = reinterpret_cast<URLCTRL *>(::GetProp(hwnd, _T("UrlCtrl")));
		if(url != NULL)
		{
			HANDLE hOld = NULL;
			DWORD style = DT_SINGLELINE | DT_NOPREFIX;
			RECT rc = {0};

			int len = 2 + ::GetWindowTextLength(hwnd);
			sized_array<TCHAR> szText(len);
			::GetWindowText(hwnd, szText.get(), len);

			if(url->dwFlags & UCF_TXT_RIGHT)
				style |= DT_RIGHT;
			else if(url->dwFlags & UCF_TXT_HCENTER)
				style |= DT_CENTER;

			if (url->dwFlags & UCF_TXT_BOTTOM)
				style |= DT_BOTTOM;
			else if(url->dwFlags & UCF_TXT_VCENTER)
				style |= DT_VCENTER;

			if(calcrect == NULL)
			{/* draw! */
				COLORREF crOldText = {0};
				int iOldBkMode = 0;

				::GetClientRect(hwnd, &rc);
				::FillRect( hdc, &rc, reinterpret_cast<HBRUSH>(COLOR_3DFACE + 1) );
				if(url->dwFlags & UCF_KBD)
				{/* protect focus rect */
					if(::GetFocus() == hwnd)
						::DrawFocusRect(hdc, &rc);
					++rc.left;
					--rc.right;
					++rc.top;
					--rc.bottom;
				}
				crOldText = ::SetTextColor(hdc, (url->dwFlags & UCF_LNK_VISITED) ? (url->crVisited) : (url->crUnvisited));
				iOldBkMode = ::SetBkMode(hdc, TRANSPARENT);
				hOld = ::SelectObject(hdc, url->hfont);
				::DrawText(hdc, szText.get(), -1, &rc, style);
				::SelectObject(hdc, hOld);
				::SetBkMode(hdc, iOldBkMode);
				::SetTextColor(hdc, crOldText);
			}
			else
			{/* just calc */
				calcrect->left = calcrect->top = 0;
				hOld = ::SelectObject(hdc, url->hfont);
				calcrect->right = calcrect->bottom = 0x00007FFF;
				/* some big value */

				::DrawText(hdc, szText.get(), -1, calcrect, style | DT_CALCRECT);
				hOld = ::SelectObject(hdc, hOld);

				if(url->dwFlags & UCF_KBD)
				{/* for focus rect */
					calcrect->right += 2;
					calcrect->bottom += 2;
				}
			}
			return TRUE;
		}
	}
	return FALSE;
}



BOOL util_url_fit(HWND hwnd, BOOL fRedraw /*= TRUE*/)
{
	BOOL fResult = FALSE;
	if( ::GetWindowLongPtr(hwnd, GWLP_WNDPROC) == reinterpret_cast<LONG_PTR>(urlctrl_proc) )
	{/* is urlctrl? */
		HDC hdc = ::GetDC(hwnd);
		if(hdc != NULL)
		{
			RECT rc = {0};
			fResult = util_url_draw(hwnd, hdc, &rc);
			/* calc rect (does NOT draw) */
			::ReleaseDC(hwnd, hdc); hdc = NULL;
			if(fResult)
			{/* apply rect */
				UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE;
				if(fRedraw == FALSE)
					flags |= SWP_NOREDRAW;
				fResult = ::SetWindowPos(hwnd, NULL, 0, 0, rc.right, rc.bottom, flags);
			}
		}
	}
	return fResult;
}



BOOL util_url_open(HWND hwnd)
{	
	BOOL fResult = FALSE;
	if( ::GetWindowLongPtr(hwnd, GWLP_WNDPROC)== reinterpret_cast<LONG_PTR>(urlctrl_proc) )
	{/* is urlctrl? */
		URLCTRL *url = reinterpret_cast<URLCTRL *>(::GetProp(hwnd, _T("UrlCtrl")));
		if(url)
		{
			::ShellExecute(NULL,_T("open"), url->szURL.get(), NULL, NULL, SW_SHOWNORMAL);
			/* open browser */
			url->dwFlags |= UCF_LNK_VISITED;
			/* set visited */
			::InvalidateRect(hwnd, NULL, TRUE);
			::UpdateWindow(hwnd);
			fResult = TRUE;
		}
	}
	return fResult;
}



LRESULT CALLBACK urlctrl_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	URLCTRL *url = reinterpret_cast<URLCTRL *>(::GetProp(hwnd, _T("UrlCtrl")));
	WNDPROC oldproc = url->oldproc;
	switch(uMsg)
	{
		case WM_NCDESTROY:
		{
			::SetWindowLongPtr(hwnd, GWLP_WNDPROC, LONG_PTR2(reinterpret_cast<void *>(oldproc)));
			if(url->hcur) ::DestroyCursor(url->hcur);
			if(url->hfont) ::DeleteObject(url->hfont);
			delete [] url; url = NULL;
			::RemoveProp(hwnd, _T("UrlCtrl"));
			break;
		}

		case WM_PAINT:
		{
			PAINTSTRUCT ps = {0};
			HDC hdc = reinterpret_cast<HDC>(wParam);
			if(wParam == 0)
				hdc = ::BeginPaint(hwnd, &ps);
			if(hdc)
			{
				util_url_draw(hwnd, hdc, NULL);
				if(wParam==0) ::EndPaint(hwnd, &ps);
			}
			return 0;
		}

		case WM_SETTEXT:
		{
			LRESULT result = ::CallWindowProc(oldproc, hwnd, uMsg, wParam, lParam);
			if(url->dwFlags & UCF_FIT)
				util_url_fit(hwnd, FALSE);
			::InvalidateRect(hwnd, NULL, TRUE);
			::UpdateWindow(hwnd);
			return result;
		}


		case WM_SETCURSOR:
		{
			HCURSOR hcur = url->hcur;
			if(hcur == NULL) hcur = ::LoadCursor(NULL, IDC_ARROW);
			/* fall back */
			::SetCursor(hcur);
			return 1;
		}

		case WM_NCHITTEST:
		{/* static returns HTTRANSPARENT (prevents receiving mouse msgs) */
			return HTCLIENT;
		}


		case WM_SETFONT: //we always modify the font!
		{
			LOGFONT lf = {0};
			HFONT hfont = reinterpret_cast<HFONT> (wParam);
			if(hfont == NULL)
				hfont = reinterpret_cast<HFONT>(::GetStockObject(SYSTEM_FONT));
			::GetObject(hfont, sizeof(LOGFONT), &lf);
			lf.lfUnderline = TRUE;
			/* add underline */
			if(url->hfont)
			{/* delete old font */
				::DeleteObject(url->hfont);
			}
			url->hfont = ::CreateFontIndirect(&lf);
			/* create new font */
			::CallWindowProc(oldproc, hwnd, uMsg, wParam, 0);
			/* block redraw */
			if(url->dwFlags & UCF_FIT)
				util_url_fit(hwnd, FALSE);
			if(LOWORD(lParam))
			{/* redraw? */
				::InvalidateRect(hwnd, NULL, TRUE);
				::UpdateWindow(hwnd);
			}
			return 0;
		}

		case WM_LBUTTONDOWN:
		{
			if(url->dwFlags & UCF_KBD) ::SetFocus(hwnd);
			::SetCapture(hwnd);
			url->fClicking = TRUE;
			break;
		}

		case WM_LBUTTONUP:
		{
			::ReleaseCapture();
			if(url->fClicking)
			{
				POINT pt = {0};
				RECT rc = {0};
				url->fClicking = FALSE;
				pt.x=static_cast<short>(LOWORD(lParam));
				pt.y=static_cast<short>(HIWORD(lParam));
				::ClientToScreen(hwnd, &pt);
				::GetWindowRect(hwnd, &rc);
				if(::PtInRect(&rc,pt))/* inside? */
					util_url_open(hwnd);
			}
			break;
		}

		case WM_KEYDOWN:
		{
			if(url->dwFlags & UCF_KBD)
			{
				if(wParam == VK_SPACE)
				{
					util_url_open(hwnd);
					return 0;
				}
			}
			break;
		}
		case WM_KEYUP:
		{
			if(url->dwFlags & UCF_KBD)
			{
				if(wParam == VK_SPACE)
				{
					return 0;
				}
			}
			break;
		}

		case WM_GETDLGCODE:
		{
			if(url->dwFlags & UCF_KBD)
				return DLGC_WANTCHARS;
			break;
		}

		case WM_SETFOCUS:
		case WM_KILLFOCUS:
		{
			if(url->dwFlags & UCF_KBD)
			{
				::InvalidateRect(hwnd, NULL, TRUE);
				::UpdateWindow(hwnd);
				return 0;
			}
			break;
		}
	}
	return ::CallWindowProc(oldproc, hwnd, uMsg, wParam, lParam);
}



BOOL urlctrl_set(HWND hwnd, const std::basic_string<TCHAR> &szURL,
	COLORREF unvisited /*= RGB(0,0,255)*/, COLORREF visited /*= RGB(128,0,128)*/, DWORD dwFlags /*= UCF_KBD*/)
{
	if(::IsWindow(hwnd))
	{
		URLCTRL *url = NULL;
		if(::GetWindowLongPtr(hwnd, GWLP_WNDPROC) == LONG_PTR2(reinterpret_cast<void *>(urlctrl_proc)))
		{/* update old */
			throw STD(_T("Inited a URL control more than once"));
		}
		else
		{/* create new */
			url = new URLCTRL[1];
			/* init once */

			HFONT hfont = reinterpret_cast<HFONT>(::SendMessage(hwnd, WM_GETFONT, 0, 0));
			url->oldproc = reinterpret_cast<WNDPROC>(static_cast<LONG_PTR>
				(::SetWindowLongPtr(hwnd, GWLP_WNDPROC, LONG_PTR2(reinterpret_cast<void *>(urlctrl_proc)))));
			::SetProp(hwnd, _T("UrlCtrl"), url);
			/* store in control */
			url->fClicking = FALSE;
			url->hcur = ::LoadCursor(NULL, IDC_HAND);
			/* modify current font */
			::SendMessage(hwnd, WM_SETFONT, reinterpret_cast<WPARAM>(hfont), 0);
		}

		/* init always */
		LONG style = ::GetWindowLong(hwnd, GWL_STYLE);
		url->szURL.reset(szURL.size() + 2);
		url->szURL = szURL;
		//szURL.copy(url->szURL.get(), szURL.size(), 0);

		url->crUnvisited = (unvisited);
		url->crVisited = (visited);

		url->dwFlags = dwFlags;
		style &= ~(WS_BORDER | WS_TABSTOP);//remove
		style |= SS_NOTIFY;//add

		if(url->dwFlags & UCF_KBD)
			style |= WS_TABSTOP;//add?

		::SetWindowLong(hwnd, GWL_STYLE, style);

		if(url->dwFlags & UCF_FIT)
			util_url_fit(hwnd, FALSE);

		::InvalidateRect(hwnd, NULL, TRUE);
		::UpdateWindow(hwnd);
	}
	return TRUE;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Mr. Shah is a reclusive C++/C# developer lurking somewhere in the depths of the city of London. He learnt physics at Kings' College London and obtained a Master in Science there. Having earned an MCAD, he teeters on the brink of transitioning from C++ to C#, unsure of which language to jump to. Fortunately, he also knows how to use .NET interop to merge code between the two languages (which means he won't have to make the choice anytime soon).

His interests (apart from programming) are walking, football (the real one!), philosophy, history, retro-gaming, strategy gaming, and any good game in general.

He maintains a website / blog / FAQ / junk at shexec32.serveftp.net, where he places the best answers he's written to the questions you've asked. If you can find him, maybe you can hire Mr. Shah to help you with anything C++[/CLI]/C#/.NET related Smile | :) .

Comments and Discussions