[함수] GD 를 이용한 통계용그래프 수정안2

출처 : http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=37178

오래전 만들어 올렷던 건데 좀 수정을 했습니다.
그라디에이션효과를 프로그램이 아닌 배경이미지를 이용해 나타냈고,
막대에 모양을 좀 이쁘게 했습니다.
링크에서 그라디에이션배경이미지 3개를 다른이름으로 저장해서 파일과
같은 경로에 넣어주세요. 그리고 ariali.ttf 폰트로 필요하니 윈도우에 있는 폰트파일
복사해다 같은 위치에 넣주세요.
----------------------------------------------------------------------
<?
class gdGraph{
function mainCall($data,$h,$margin="50",$weight="10",$copy="",$write){
//폰트가 있는 위치를 적어준다. /나 ./로 시작해 적어준다
$this->font = "./ariali.ttf";
//각각의 받은 값을 세팅
$this->data = $data;
$this->margin = $margin;
$this->copystr = $copy;
$this->weight = $weight;
if ($this->copystr) $this->copyright = 20;//카피라이트가 있다면 스여질공간 20확보
$this->h = $h;//이미지의 높이
$this->w = $this->margin * 2 + sizeof($this->data) * $this->weight;//이미지의 넓이

//각각의 역할을 하는 함수들 호출
$this->base();//이미지바탕을만든다
$this->gradation();//바탕의 그라디에이션효과
$this->nomograph();//가로세로선을 그린다
$this->selectmax();//맥스값을 구한다
$this->drawclumn();//막대를 그린다
if($write) $this->charwrite();//좌측에 쓰여지는 수치값
if($write) $this->numberwrite();//막대에 쓰여지는 수치값
if($write) $this->datewrite();//하단에 쓰여지는 수치값
$this->copywrite();//우측 카피라이트

//이미지출력
header('Content-type: image/png');
imagepng($this->image);
imagedestroy($this->image);
}
function base(){
$this->image = imagecreate($this->w + $this->copyright, $this->h);
$this->black = imagecolorallocate($this->image, 0, 0, 0);//검은색
$this->white = imagecolorallocate($this->image, 255, 255, 255);//흰색
$this->light_green = imagecolorallocate($this->image, 0, 183, 0);//가로줄, 세로줄의 색
$this->dark_green = imagecolorallocate($this->image, 153, 218, 148);//가로줄, 세로줄의 색
$this->bgcolor = imagecolorallocate($this->image, 215, 215, 215);//배경 회색
imagefill($this->image, 0, 0, $this->bgcolor);
}
function gradation(){
/*
배경에 그라디에이션을 넣는 부분인데 그라디에이션배경을 처리하면 막대의 그라디에이션이 깨진다.
아직 GD가 제대로 지원을 못하는 듯한데 같은 계열의 색을 배경으로 하면 깨지지 않는다.
하지만 초록색막대에 초록색 배경을 써야하니 이상하다.
아래 주석을 제거하면 볼 수 있다. 푸른색은 깨지고 녹색은 된다
*/
//$image = imagecreatefromgif("./rad01.gif");//푸른바탕은 이미지가 깨지다
//$image = imagecreatefromgif("./rad02.gif");//녹색바탕은 제대로 나온다
//imagecopyresized($this->image, $image, 0, 0, 0, 0, $this->w, $this->h, 200, 200);
}
function nomograph(){
//세로줄
imageline($this->image, $this->margin, $this->margin, $this->margin ,$this->h - $this->margin, $this->light_green);
imageline($this->image, $this->w - $this->margin, $this->margin, $this->w - $this->margin ,$this->h - $this->margin, $this->light_green);
//가로줄은 밝은녹색과 어두운녹색을 일정한 형식으로 반복해 그린다
if($this->h - $this->margin * 2 < 200) $tmp_cell=10;
else if ($this->h - $this->margin * 2 < 400) $tmp_cell=20;
else $tmp_cell=40;
$tmp_h=($this->h - $this->margin * 2) / $tmp_cell;
for ($i = 0 ; $i <= $tmp_cell ; $i++){
$tmp_he = $this->margin + $i * $tmp_h;
imageline($this->image, $this->margin - 3, $tmp_he, $this->w - $this->margin + 3, $tmp_he, ($i % ($tmp_cell / 10))?$this->dark_green:$this->light_green);
}
}
function selectmax(){
//그래프의 최대값을 구한다.
for ($i = 0 ; $i < sizeof($this->data) ; $i++){
if ($max < $this->data[$i]) $max = $this->data[$i];
}
$this->maxvalue=$max;
}
function drawclumn(){
for($i = 0 ; $i < sizeof($this->data) ; $i++){
//막대의 높이
$tmp_hvalue = ($this->h - $this->margin * 2) - $this->data[$i]/$this->maxvalue * ($this->h - $this->margin * 2) + $this->margin;
//막대의 그라디에이션
$image = imagecreatefromgif("./rad11.gif");
imagecopyresized($this->image, $image, $this->margin + $i * $this->weight + 1, $tmp_hvalue, 0, 0, $this->weight - 1, $this->h - $tmp_hvalue - $this->margin, 200, 200);
//막대의 외형모양을 꾸미는 라인들
imageline($this->image, $this->margin + $i * $this->weight + 1, $tmp_hvalue, $this->margin + $i * $this->weight + $this->weight, $tmp_hvalue, $this->white);
imageline($this->image, $this->margin + $i * $this->weight + 1, $tmp_hvalue, $this->margin + $i * $this->weight + 1, $this->h - $this->margin, $this->white);
imageline($this->image, $this->margin + $i * $this->weight + $this->weight, $tmp_hvalue, $this->margin + $i * $this->weight + $this->weight, $this->h - $this->margin, $this->black);
}
}
function charwrite(){
//우측글자쓰기
for ($i = 0 ; $i <= 10 ; $i++){
$value = round($this->maxvalue * (10 - $i) / 10,1);
$arr_size = imagettfbbox(7, 0, $this->font, $value);
$width = abs($arr_size[2] - $arr_size[0]);
$we = round($this->margin - $width - 10);
$height = abs($arr_size[5] - $arr_sixe[3]);
$he = round($height / 2);
$he = $this->margin + $i * (($this->h - $this->margin * 2) / 10) + $he;
imagettftext($this->image, 7 ,0, $we, $he, $this->black, $this->font, $value);
}
}
function numberwrite(){
//막대에 숫자쓰기
for($i = 0 ; $i < sizeof($this->data) ; $i++){
//글자의 높이
$tmp_hvalue = ($this->h - $this->margin * 2) - $this->data[$i]/$this->maxvalue * ($this->h - $this->margin * 2) + $this->margin;
//DATA수치쓰기
imagettftext($this->image, 7, 270, $this->margin + $i * $this->weight + 5,$tmp_hvalue + 2, $this->white, $this->font, $this->data[$i]);
}
}
function datewrite(){
//하단글자쓰기
for($i = 0 ; $i < sizeof($this->data) ; $i++){
if((($i + 1) % 5)==0 && $i){
$arr_size=imagettfbbox(7, 0, $this->font, $i + 1);
$width=abs($arr_size[2]-$arr_size[0]);
$we = ($this->weight - $width) / 2;
imagettftext($this->image, 7, 0, $this->margin + $i * $this->weight + $we, $this->h - $this->margin + 10, $this->black, $this->font, $i + 1);
}
}
}
function copywrite(){
if ($this->copystr){
//검은색으로 바탕을 만든다
imagefilledrectangle($this->image, $this->w, 0, $this->w + $this->copyright, $this->h, $this->black);
//글자의 키기를 구해 위치를 계산 중앙에 쓰여지게 한다
$arr_size=imagettfbbox(9, 270, $this->font, $this->copystr);
$height = abs($arr_size[5] - $arr_sixe[3]);
$he = round(($this->h - $height) / 2);
imagettftext($this->image, 9, 270, $this->w + 5, $he, $this->white, $this->font, $this->copystr);
}
}
}

//입력되는 데이터로 디비에서 불러와 처리해도 된다.
$arr_data=array(10,32,53,24,25,76,87,18,69,100,41,42,13,34,15,76,97,18,79,20,81,42,53,24,85,26,17,28,39,50,30);

//이미지의 높이
$height=500;

//이미지의 상하좌우여백
$margin=50;

//막대하나의 굵기
$weight=15;

//우측 카피라이트, 없으면 안나타남
$copy="Copyright CINUAE All rights reserved.";

//좌측과 하단, 막대의 숫자를 표시할 것인가를 결정(0,1)
$write=1;

//새로운 클래스를 만들어 호출
$mygdGraph=new gdGraph;
$mygdGraph->mainCall($arr_data,$height,$margin,$weight,$copy,$write);
?>

php 그래프 그리기

<?
header("Content-Type:image/jpeg");
$img = ImageCreate(200,200);
$black = ImageColorAllocate($img,0,0,0);
$white = ImageColorAllocate($img,255,255,255);
Imageline($img, 10,50,95,130,$white);
Imageline($img, 95,130,190,150,$white);
imagejpeg($img);
imagedestroy($img);

//사각형 이미지그래프 그리기

imagefilledrectangle($img,10,50,50,200,$black);

-string($img,10,120,0,"_",$색);
?>

'Computer Science' 카테고리의 다른 글

JSP 요약  (0) 2009.04.22
JSP 기초 강좌 사이트  (0) 2009.04.22
C# USB viewer open source  (0) 2009.04.22
Writing Data CDs  (0) 2009.04.22
파이썬으로 하는 웹 클라이언트 프로그래밍  (0) 2009.04.22

'Computer Science' 카테고리의 다른 글

JSP 기초 강좌 사이트  (0) 2009.04.22
php 그래프 그리기  (0) 2009.04.22
Writing Data CDs  (0) 2009.04.22
파이썬으로 하는 웹 클라이언트 프로그래밍  (0) 2009.04.22
TCP/IP 소켓 프로그래밍 with C#  (0) 2009.04.22

Writing Data CDs

출처 : http://www.vbaccelerator.com/home/net/code/Libraries/Writing_CDs/Writing_Data_CDs/article.asp

Simple Data CD Creator Application

This article demonstrates how to use the IMAPI wrapper to burn data CDs (also known as "Joliet" format CDs). Sample code is provided in both C# and VB.

Writing Data CDs

Before you begin, note that this sample uses the IMAPI Wrapper for the CD burning functions. To run the sample, you will need to have acclImapiWrapper.DLL registered in the Global Assembly cache (GAC). If you place the DLL next to the executable in your Debug or Release directory then you will also be able to run (but you may need to change the project references to run in VS.NET).

Recording a data CD using IMAPI involves performing the following steps:

  1. Initialise the library by obtaining a DiscMaster instance, setting the active mastering format to Joliet to obtain a JolietDiscMaster instance to build up the staging image that will be burnt to disc, and setting the active recorder.
  2. Constructing a JolietDiscMasterStorage hierarchy to represent the files you want to burn to disc, and their filenames on disc.
  3. Instructing JolietDiscMaster to copy the files from the JolietDiscMasterStorage to the disc image, and then burning the CD.

During the last step, the DiscMaster will raise a number of events describing progress as the disc is staged or burnt, and also allows the burn to be cancelled.

I'll describe these steps briefly with VB.NET code examples. The C# code is very similar; refer to the downloads for details.

1. Initialising the Library

The only directly instantiable class in the IMAPI Wrapper is the DiscMaster object, from which all other classes can be obtained. This can be declared WithEvents in VB because you'll want to catch the progress and cancel events. Next, the recording mode is set by obtaining a JolietDiscMaster object. A reference to the returned object is kept as this is needed to stage the image (calling the JolietDiscMaster() again will result in a new instance being returned). Having done that, the list of recorders is populated into a ComboBox and the selected index set.

    Private WithEvents discMaster As discMaster = Nothing    Private jolietDiscMaster As JolietDiscMaster = Nothing    Private Sub GetRecorders()        Dim ex As Exception        Try            discMaster = New DiscMaster()            jolietDiscMaster = discMaster.JolietDiscMaster()            Dim recorder As DiscRecorder            For Each recorder In discMaster.DiscRecorders                cboRecorder.Items.Add( _                 New ComboRecorderWrapper(recorder))            Next            If (cboRecorder.Items.Count > 0) Then                cboRecorder.SelectedIndex = 0            End If        Catch ex            MessageBox.Show( _                Me, String.Format("Unable to initialise the IMAPI library {0}", ex), _                Text, MessageBoxButtons.OK, MessageBoxIcon.Stop)            If Not (discMaster Is Nothing) Then                discMaster.Dispose()            End If        End Try    End Sub    Private Sub cboRecorder_SelectedIndexChanged( _            ByVal sender As Object, _            ByVal e As System.EventArgs _        ) Handles cboRecorder.SelectedIndexChanged        If (cboRecorder.SelectedIndex > -1) Then            Dim wrapper As ComboRecorderWrapper = cboRecorder.SelectedItem            discMaster.DiscRecorders.ActiveDiscRecorder = wrapper.DiscRecorder        End If    End Sub

As noted in the IMAPI Wrapper article, you must ensure that the Dispose method is called on the DiscMaster instance before ending your application. Failure to do this will result in any subsequent attempt to access the library failing with a "Stash In Use" error. To ensure this occurs, I've included an Application ThreadException handler, which is called in the unfortunate event of an untrapped exception in the code:

    Public Sub New()	' ...         'Add any initialization after the InitializeComponent() call        AddHandler Application.ThreadException,             AddressOf application_ThreadException              Show()        Refresh()        GetRecorders()    End Sub    Private Sub application_ThreadException( _        ByVal sender As Object, _        ByVal e As ThreadExceptionEventArgs)        MessageBox.Show(Me, _           String.Format("An untrapped exception occurred: {0}.", _             e.Exception), _             Text, MessageBoxButtons.OK, MessageBoxIcon.Error)        Close()    End Sub    Protected Overrides Sub OnClosing( _        ByVal e As System.ComponentModel.CancelEventArgs)        ' ....        '// Clear up:        MyBase.OnClosing(e)        Cursor.Current = Cursors.WaitCursor        sbrMain.Text = "Closing IMAPI interface..."        jolietDiscMaster.Dispose()        discMaster.Dispose()        Cursor.Current = Cursors.Default    End Sub

In this sample I'm exposing the stack trace of the exception directly; in a real application this would be bad practice and really the exception should be logged and a more descriptive message shown.

2. Constructing a JolietDiscMasterStorage hierarchy

The JolietDiscMaster instance exposes a RootStorage property, which returns a JolietDiscMasterStorage instance representing the root directory of the CD. You can add files and/or sub-directories to this object; sub-directories are also represented as JolietDiscMasterStorage objects. When adding a file, you specify the path of the file to copy from on disc and the name of the file in the directory to write it out to. Sub-directories just have a name. For the purposes of the sample, I just allow a directory to be added and optionally recursed:

    ''' <summary>    ''' Adds a directory to the storage, optionally including    ''' any subdirectories.    ''' </summary>    ''' <param name="path">Path to the directory to add</param>    ''' <param name="recurse"><c>true</c> to include subdirectories,    ''' <c>false</c> otherwise.</param>    Public Sub AddDirectory(ByVal path As String, ByVal recurse As Boolean)        Dim storage As JolietDiscMasterStorage = jolietDiscMaster.RootStorage        AddFilesToStorage(storage, path, recurse)    End Sub    Private Sub AddFilesToStorage( _        ByVal storage As JolietDiscMasterStorage, _        ByVal startPath As String, _        ByVal recurse As Boolean)        If (recurse) Then            Dim dir As String            For Each dir In Directory.GetDirectories(startPath)                Dim subStorage As JolietDiscMasterStorage = _                    storage.CreateSubFolder(Path.GetFileName(dir))                AddFilesToStorage(subStorage, dir, recurse)                        Next        End If        Dim file As String        For Each file In Directory.GetFiles(startPath)            storage.AddFile(file, Path.GetFileName(file))        Next    End Sub

Burning the Disc

With that done, creating the disc is easy: firstly any existing content in the image is cleared, then data is added using the AddData method of JolietDiscMaster and finally the disc is recorded using the DiscMasterRecordDisc method:

    ''' <summary>    ''' Creates a data CD from the specified files    ''' </summary>    ''' <param name="simulate">Simulate CD burning</param>    ''' <param name="ejectWhenComplete"><c>true</c> to eject the CD    ''' tray when the burn is complete, <c>false</c> otherwise</param>    ''' <param name="overwrite"><c>true</c> to overwrite existing files    ''' on CDRW media, <c>false</c> otherwise</param>    Public Sub CreateCD( _              ByVal simulate As Boolean, _              ByVal ejectWhenComplete As Boolean, _              ByVal overwrite As Boolean        )        '// Ensure we don't have anything in the stage        discMaster.ClearFormatContent()        '// Stage the content        jolietDiscMaster.AddData(overwrite)        '// burn the disc        discMaster.RecordDisc(simulate, ejectWhenComplete)        '// Easy!    End Sub

Whilst burning is in progress, there are six events to respond to:

  1. AddProgress - raised as files are added to the image.
  2. PreparingBurn - raised once the image has been created and the CD is about to burnt.
  3. BlockProgress - raised as blocks are burnt to disc (a block is 2048 bytes).
  4. ClosingDisc - raised once the burn has completed and the CD (or session) is about to be closed.
  5. Complete - raised when the burn has completed.
  6. QueryCancel - raised whilst data is added to the image or burning is in progress. Setting the Cancel property of the event arguments will cancel the operation.

That is really all you need to do to create the disc; however, if you want to be able to respond to cancellations, or to show progress you will need to write your application so the burn runs on a background thread. The construction of the wrapper makes this very easy to do using BeginInvoke.

Using BeginInvoke for a Smooth User Experience

Buring a CD is typically a long operation. If you invoke a burn operation on the user-interface thread, then the application will appear to be locked up whilst the burn occurs. Under XP and above, a feature was added which allows the caption and border of the window to be unfrozen if XP detects that the application has been locked up for a significant length of time. After this point in .NET Framework applications, calls to update controls and so forth no longer have any effect.

Therefore we want a way to invoke the CD burn on a background thread. Since the IMAPI wrapper makes a call to check whether the burn is cancelled at frequent intervals, and this is done through an event, there is also a safe way to cancel a burn operation at any time.

Any method in a class can be invoked asynchronously in .NET by creating a delegate for it. Once you have done this, the compiler is responsible for automatically creating three methods for the delegate:

  1. The Invoke method, which has the same parameters and return value as the delegate and allows the method to be called synchronously.
  2. The BeginInvoke method, which is the same as Invoke except it adds two more parameters: an AsyncCallback delegate and an object to hold state.
  3. The EndInvoke method, which the same return value as the delegate, any ref or out parameters and an extra parameter holding an IAsyncResult object.

This makes asynchronous invocation easy. There are four coding steps:

  1. Declare a delegate for the method you want to call asynchronously.
  2. Write a completion event handler for the method you want to call, which will be called when the method completes.
  3. Create an AsyncCallback handler and connect it to your completion event handler.
  4. Invoke the delegate's method asynchronously using BeginInvoke.

Here's the code for doing this in VB and C#. Unsurprisingly the code is very similar; the only real difference being VB's odd use of AddressOf to refer to delegates. In this case the method I want to call is the CreateCD method implemented in my DataCDCreator class. This method takes three boolean parameters (for simulate burn, eject when complete and overwrite) and has no return value:

VB Code for Asynchronous Invocation

''' <summary>''' Delegate representing the CreateCD method''' </summary>Public Delegate Sub CreateCDDelegate( _    ByVal simulate As Boolean, _    ByVal ejectWhenComplete As Boolean, _    ByVal overwrite As Boolean)
    Private creator As DataCDCreator = Nothing    Private createCDHandler As CreateCDDelegate = Nothing        ' Asynchronously invoke the creator        creator = New DataCDCreator(discMaster, jolietDiscMaster)        creator.AddDirectory(txtFolder.Text, True)        createCDHandler = AddressOf creator.CreateCD        Dim callback As AsyncCallback = AddressOf createCD_Complete        Dim ar As IAsyncResult = createCDHandler.BeginInvoke( _            simulate, ejectWhenComplete, overwrite, callback, Nothing)    ''' <summary>    ''' Called when CD creation completes    ''' </summary>    ''' <param name="ar">Result of method call (none)</param>    Private Sub createCD_Complete(ByVal ar As IAsyncResult)        ' NB should surround with try - catch - end try        SetApplicationMode(False)        createCDHandler.EndInvoke(ar)    End Sub

C# Code for Asynchronous Invocation

   /// <summary>   /// Delegate representing the CreateCD method   /// </summary>   public delegate void CreateCDDelegate(       bool simulate,        bool ejectWhenComplete,        bool overwrite);
      private DataCDCreator creator = null;      private CreateCDDelegate createCDHandler = null;        // Asynchronously invoke the creator        creator = new DataCDCreator(discMaster, jolietDiscMaster);        creator.AddDirectory(txtFolder.Text, true);                       createCDHandler = new CreateCDDelegate(creator.CreateCD);        AsyncCallback callback = new AsyncCallback(createCD_Complete);        IAsyncResult ar = createCDHandler.BeginInvoke(            simulate, ejectWhenComplete, overwrite, callback, null);      /// <summary>      /// Called when CD creation completes      /// </summary>      /// <param name="ar">Result of method call (none)</param>      private void createCD_Complete(IAsyncResult ar)      {         // NB should surround with try-catch         SetApplicationMode(false);         createCDHandler.EndInvoke(ar);      }

More Ideas

The sample application here is rather trivial, in that all it allows you to do is to copy an existing directory to the CD. However, that's not an actual limitation, since when you create the storage you can specify that any file is mapped to a different path and or file on the destination CD. A more complete application would allow you to drag files from any location to the CD, and rename them if possible.

You could use this code to create an almost unattended CD writer (the only thing you need to do is to ensure suitable media is available in the drive) rather than having a UI.

Conclusion

This article demonstrates how to create Data CDs from VB or C# using the IMAPI Wrapper. Although the sample has a simple UI it performs all of the major operations you'll need to perform and should be easy to extend.

'Computer Science' 카테고리의 다른 글

php 그래프 그리기  (0) 2009.04.22
C# USB viewer open source  (0) 2009.04.22
파이썬으로 하는 웹 클라이언트 프로그래밍  (0) 2009.04.22
TCP/IP 소켓 프로그래밍 with C#  (0) 2009.04.22
Delphi for php 사용안내  (0) 2009.04.22
파이썬으로 하는 웹 클라이언트 프로그래밍
저자: 데이브 워너(Dave Warner), 역 전순재

웹 클라이언트 프로그래밍은 웹에서 정보를 찾게 도와주는 강력한 테크닉이다. 웹 클라이언트는 (웹 주소 앞에 붙은 http) 하이퍼 텍스트 전송 프로토콜[1]을 사용하여 웹 서버로부터 데이터를 열람하는 프로그램 모두를 말한다. 웹 브라우저는 클라이언트이다. 웹 크롤러(crawler) 역시 클라이언트이다. 이 프로그램은 웹을 자동적으로 돌아다니면서 정보를 수집한다. 웹 클라이언트를 사용하면 웹에서 다른 사람들이 제공하는 서비스들을 이용할 수 있으며 웹 사이트에 역동적인 특징들을 추가할 수도 있다.

개발자들이 사용하는 툴박스에는 자연스럽게 웹 클라이언트 프로그래밍이 들어있다. 펄(Perl) 열성팬들은 이미 수년간 웹 클라이언트 프로그래밍을 이용해 왔다. 이런 웹 클라이언트 프로그래밍은 파이썬으로 처리하면 편리성과 유연성이 더욱 높은 수준에 이른다. 여기에 필요한 모든 기능들은 모듈 3개로 해결할 수 있다. HTTPLIB, URLLIB, 그리고 더 새로워진 XMLRPCLIB가 바로 그것들이다. 진정한 파이썬 스타일로, 각 모듈은 기존의 모듈 위에 구축되어 애플리케이션에 견고하면서도 잘 디자인된 기반을 제공한다. XMLRPCLIB는 다음에 논하기로 하고 본 기사에서는 첫 번째 모듈 두 개에 대해 다루겠다.

우리가 볼 예제에서는 미어캣(Meerkat)을 사용하겠다. 이럴 경우 여러분이 필자와 같은 생각을 가지고 있다면 시간을 들여 오픈 소스 공동체의 동향과 개발 상황들을 추적해서 경쟁력을 확보할 것이다. 미어캣(Meerkat) 은 이 작업을 훨씬 더 쉽게 만들어주는 도구이다. 미어켓은 오픈 와이어 서비스(open wire service)로서 오픈 소스 컴퓨팅과 관련된 방대한 양의 정보를 수집하고 정리한다. 미어캣의 브라우저 인터페이스는 유연하고 맞춤가능하지만, 웹 클라이언트 프로그래밍을 사용하면 우리는 이 정보를 훓어보고, 추출하는 것은 물론이고 나중에 사용하기 위해 오프 라인에 저장할 수도 있다. 우리는 먼저 HTTPLIB를 상호대화적으로 사용하여 미어켓에 접근할 것이다. 그리고 나서 URLLIB를 통해 미어켓의 개방 API(Meerkat's Open API)에 접근해 들어가 맞춤가능한 정보 수집도구를 만들어 볼 것이다.

HTTPLIB

HTTPLIB 는 소켓(socket) 모듈을 살짝 감싼 포장자(wrapper)이다. 앞에서 언급한 3개의 라이브러리 중에서 웹 사이트에 접근할 때 가장 제어가 쉬운 모듈이 HTTPLIB이다. 그렇지만 과업을 달성하기 위해서는 추가 작업을 더 해야만 제대로 제어할 수 있다. http 통신규약(protocol)은 "정보를 저장하지 않기(stateless)" 때문이다. 따라서 이전의 요구는 전혀 기억하지 않는다. 각 요구에 대해 여러분은 HTTPLIB 객체를 새롭게 구성하여 웹 사이트에 접속해야 한다. 요구들은 웹 서버와 대화를 형성하고 웹 브라우저를 흉내낸다. 라엘 돈페스트(Rael Dornfest)의 개방 API를 사용해서 미어켓에 접속해 보자. 그리고 어떤 결과를 얻는지 살펴 보자. 대화는 일련의 서술문들을 구축함으로써 시작된다. 먼저 원하는 작업이 무엇인지 서술한다. 그리고 나서 웹 서버에게 여러분을 식별시킨다.
>>> import httplib>>> host = 'www.oreillynet.com'>>> h = httplib.HTTP(host)>>> h.putrequest('GET', '/meerkat/?_fl=minimal')>>> h.putheader('Host', host)>>> h.putheader('User-agent', 'python-httplib')>>> h.endheaders()>>>
GET 요청은 어느 페이지를 받기 원하는지 서버에게 전달한다. 호스트 헤더(Host header)는 질의하고자 하는 도메인 이름을 서버에게 전달한다. 현대적인 서버들은 HTTP 1.1을 사용하여 여러 도메인을 같은 주소에서 사용할 수 있다. 만약 서버에게 어떤 도메인 이름을 원하는지 알려주지 않는다면, 여러분은 '302' 출력전환(redirection) 응답을 반환 코드로 얻게 될 것이다. 사용자-에이전트 헤더(User-agent header)는 서버에게 여러분이 어떤 종류의 클라이언트인지 알려 준다. 그래야만 서버는 여러분에게 보낼 수 있는 것과 없는 것이 무엇인지를 이해할 수 있기 때문이다. 이것이 웹 서버가 요구를 처리하기 위해 필요한 정보이다. 다음으로 여러분은 응답을 요구한다.
>>> returncode, returnmsg, headers = h.getreply()>>> if returncode == 200:  #OK...         f = h.getfile()...         print f.read()...
이렇게 하면 현재의 미어켓 페이지를 간략한 형태(minimal flavor)로 출력할 것이다. 응답 머리부와 응답 내용은 개별적으로 반환되며, 이렇게 하면 반환된 데이터의 문제를 해결하거나 해석하는데 모두 도움이 된다. 만약 응답 머리부를 보고 싶다면, print headers를 사용하면 된다.

HTTPLIB 모듈은 소켓 프로그래밍의 기계적인 면을 구별해준다. 게다가 HTTPLIB 모듈은 버퍼링을 위해 파일 객체를 사용하기 때문에 친숙하게 데이터 조작에 접근할 수 있지만 더욱 강력한 웹 클라이언트 애플리케이션을 위한 빌딩 블록이나 문제가 생긴 웹사이트와 상호 대화를 나누기 위한 빌딩 블록으로 더 잘 맞는다. HTTPLIB 모듈이 가지는 유용한 디버그 능력은 두 영역 모두에 도움을 준다. 객체 초기화 후에 어느 곳에서나
h.set_debuglevel(1) 메소드를 호출하면 HTTPLIB에 접근할 수 있다. (예제에서는 다음의 h = httplib.HTTP(host) 라인이다). 디버그 수준이 1에 설정되어 있으면 HTTPLIB 모듈은 getreply()을 호출한 결과들과 요청들을 화면에 응답할 것이다.

파 이썬의 상호대화적인 특성 덕분에 즐겁게 HTTPLIB를 사용하여 웹 사이트를 분석할 수 있다. 이 모듈을 익히면 웹 사이트의 문제점들을 진단하기 위한 강력하고 유연한 도구를 가지게 되는 것이다. 또 시간을 가지고 HTTPLIB에 대한 소스를 살펴보라. 200줄도 안되는 코드임에도 불구하고, HTTPLIB를 사용하면 빠르고 쉽게 파이썬으로 소켓 프로그래밍을 시작할 수 있다.

URLLIB

URLLIB 는 HTTPLIB에서 발견되는 기능에 대해 세련된 인터페이스를 제공한다. URLLIB 모듈은 웹 사이트를 분석하는 것보다는 데이터 그 자체를 찾아 내는데 가장 유용하게 사용된다. 다음 코드는 URLLIB를 사용해서 위와 똑같은 상호작용을 한다. (주의: 마지막 줄을 화면 출력을 위해 두 줄로 쪼개었지만, 여러분의 스크립트에서는 나누지 말 것!)
>>> import urllib>>> u = urllib.urlopen('http://www.oreillynet.com/meerkat/?_fl=minimal')
이것이 다이다! 한 줄로 미어켓(Meerkat)에 접근해서 데이터를 얻었으며, 그 데이터를 임시 저장소에 보관했다. 해더 정보에 접근하려면
>>> print u.headers
그리고 전체 파일을 보려면
>>>print u.read()
그러나 이것이 전부는 아니다. URLLIB는 HTTP뿐만 아니라 FTP, Gopher, 심지어는 같은 방식으로 지역 파일에도 접근할 수 있다. 이 모듈이 제공하는 많은 유틸리티 기능에는 url 해석하기, 문자열을 url-안전 형태로 코드전환(encode)하기, 그리고 한참 긴 데이터 전송 중에 진행 표시를 제공하기가 있다.

미어켓을 사용하는 예제 하나

한 그룹의 고객(client)들이 있는데 그들이 최신 리눅스 소식을 이메일로 꾸준히 받아보기를 바라고 있다고 상상해보자. 우리는 짧은 스크립트를 작성할 수 있다. URLLIB를 사용하여 이 정보를 Meerkat으로부터 얻는다. 링크의 목록을 구축한다. 그리고 그 링크들을 나중에 전송하기 위해 파일에 저장한다. 미어켓(Meerkat)의 저자인 라엘 돈페스트(
Rael Dornfest)는 미어켓 API를 통해 우리 대신 대부분의 작업을 이미 완성해 놓았다. 남아있는 것은 요구를 구성하고, 링크를 해석하며, 나중에 전송하기 위해 그 결과를 저장하는 것 뿐이다.

단 지 이것 때문에 사람들이 미어캣으로 전향하는 것일까? 이러한 "정보받기(passive)" 서비스를 제공하면 사람들은 그 정보를 한가할 때 볼 수 있다. 그리고 그 정보를 골라서 친숙한 형식(예를 들어 이메일)으로 저장할 수 있다. 월요일 아침에 메일함에서 뉴스들이 도착하기를 기다리기만 하면, 한 주간 "말려 올라간" 정보들을 하나도 놓치지 않을 것이다.

미어캣의 간략한 형식(minimal flavor)은 기사가 15개로 제한되므로 데이터를 놓칠 가능성을 줄이기 위해 우리는 스크립트를 (즉, Unix의 cron 작업 또는 NT의 AT 명령어를 사용하여) 매 시간 실행시킬 것이다. 여기에 우리가 사용할 url이 있다 (주의: 우리는 이 줄을 두 개의 줄로 나누어 화면에 표시했다. 이 URL을 사용한 결과는
여기에서 볼 수 있다).
http://www.oreillynet.com/meerkat/?p=5&t=1HOUR&_fl=minimal&_de=0&_ca=0&_ch=0&_da=0
이 코드는 지난 한 시간 동안에 있었던 모든 리눅스 이야기들(profile=5)을 끌어 와서, 데이터를 간략한 형식(minimal flavor)으로 보여준다. 설명도 없고, 범주정보도 없으며, 채널 정보, 데이터 정보도 없다. 우리는 또한 정규 표현식 모듈의 도움을 받아 링크 정보를 추출하고 출력결과를 추가 모드로 열려진 파일 객체로 방향전환할 것이다.

결론

우 리는 겨우 이 모듈들의 표면만을 건드려 보았다. 웹 클라이언트 작업에 사용할 수 있는 것 말고도 파이썬에는 다른 많은 네트워크 프로그래밍 모듈을 사용할 수 있다. 웹 클라이언트 프로그래밍은 특히 방대한 양의 계산표형 테이터를 다룰 때 유용하게 사용할 수 있다. 최근의 한 전자 데이터 교환(EDI) 프로젝트에서 우리는 웹 클라이언트 프로그래밍을 사용하여 거추장스러운 독점 소프트웨어 패키지를 우회하였다. 갱신된 가격 정보를 웹으로부터 직접 얻어서 데이터베이스에 집어 넣었다. 그렇게 함으로써 우리는 많은 시간을 절약하고 좌절감을 극복할 수 있었다.

웹 클라이언트 프로그래밍은 웹 사이트의 구조와 견고성을 테스트하는 데에도 유용하게 사용될 수 있다. 일반적으로는 죽은 링크들을 점검하는 방법으로 사용된다. 표준 파이썬 배포본에는 이것에 대한 완전한 예제가 딸려온다. 이 예제는 URLLIB에 기초한다. Tk-기반의 프론트 엔드
[2] 모듈인 웹체커(Webchecker)는 파이썬 배포본의 tools 하부디렉토리 아래에서 찾아볼 수 있다. 또다른 파이썬 도구인 린봇(Linbot) 은 URLLIB 모듈의 기능을 개선해 준다. 린봇으로 여러분은 웹 사이트의 문제를 모두 해결할 수 있다. 웹 사이트들이 점점 더 복잡해짐에 따라 웹 사이트의 질을 확인하기 위해서는 다른 웹 클라이언트 애플리케이션들이 필요하게 될 것이다.

웹 클라이언트 프로그래밍에는 함정이 하나 있다. 여러분의 프로그램은 페이지의 형식이 조금만 변경되어도 영향을 받는다. 반드시 웹 사이트가 오늘 데이터를 출력하는 방식이 내일도 그대로 유지된다고 장담할 수는 없다. 페이지의 형식이 바뀌면 프로그램도 바뀌어야 한다. 사람들이 XML에 그렇게 흥분하는 이유 중 하나가 바로 이것 때문이다. 웹에서 데이터에 태그를 붙여 의미를 주면 형식은 중요하지 않게 된다. XML 표준이 진화하고 범세계적으로 인정됨에 따라, 훨씬 더 쉽게 그리고 튼튼하게 XML 데이터를 처리하게 될 것이다.

우리가 여기에서 다룬 도구들에는 약간의 제한이 있다. HTTPLIB 모듈과 URLLIB모듈은 클라이언트-기반 작업에는 탁월하지만 오직 한 번에 한 개의 요청만을 처리할 수 있기 때문에 서버를 구축하는데 사용해서는 안된다. 비동기적인 처리방법을 제공하기 위해 샘 러싱(Sam Rushing)은 멋진 도구모음을 구축하였다. 이 도구모음은 asyncore.py 를 포함하여 표준 파이썬 배포본에 딸려 온다. 이 접근법을 사용하는 가장 강력한 예제는 조프(
ZOPE)이다. 조프는 애플리케이션 서버로서 샘 러싱(Sam Rushing)의 메듀사 엔진(Medusa engine)을 사용하여 구축한 빠른 http 서버를 포함하고 있다.

다음 기사에서는 XML과 웹 클라이언트 프로그래밍을 어떻게 XMLRPCLIB 모듈에 결합하는지에 대해 논의해볼 생각이다. XML을 사용하면 미어켓(Meerkat) API로부터 더욱 많은 기능을 짜낼 수 있다.
각주
[1] Hyper Text Transfer Protocol
[2] front end: 프론트 엔드
예) GUI는 front end 이며 구현된 기능들은 back end이다.

데이브 워너(Dave Warner)는 Federal Data Corporation사의 선임 프로그래머이자 데이터베이스 관리자(DBA)이다. 그는 P자로 시작하는 언어(Python, Perl, PowerBuilder)로 관계형 데이터베이스에 접근하는 방법을 연구하고 있다.
출처: Hanbit Network

'Computer Science' 카테고리의 다른 글

C# USB viewer open source  (0) 2009.04.22
Writing Data CDs  (0) 2009.04.22
TCP/IP 소켓 프로그래밍 with C#  (0) 2009.04.22
Delphi for php 사용안내  (0) 2009.04.22
flash plot  (0) 2009.04.21

'Computer Science' 카테고리의 다른 글

Writing Data CDs  (0) 2009.04.22
파이썬으로 하는 웹 클라이언트 프로그래밍  (0) 2009.04.22
Delphi for php 사용안내  (0) 2009.04.22
flash plot  (0) 2009.04.21
contextmenustrip 메뉴에 하위메뉴 동적으로 생성  (0) 2009.04.15

DELPHI FOR PHP 소개및 한글 사용 방법

webM
2009.01.16 11:35:16
Borland 와 CodeGear의 만남으로 인해 태어난 Delphi for php 프로그램을 소개 합니다. 볼랜드사는 제가 개인적으로 좋아 하는 컴파일러 전문 회사입니다.
MS-DOS 프로그램용 C언어 컴파일러인 터보C는 막강한 성능을 보였으며, 과거의 바이트지의 기억으로는 실행화일속도가 재일 빨랐던 것으로 기억합니다. MS-C와 TURBO-C 양대 산맥의 경쟁은 아주 치열했던것으로 기억합니다.MS-C 컴파일러는 DOS만든 회사에서 만든 컴파일러라서 믿고, 사용을 하던 엔지니어도 있으나, 터보C의 막강함을 따라오지 못했습니다. MS-C의 장점으로는 여러 디바이스회사에서 MS-C용 라이브러리를 지원해주고 있어서 엔지니어들의 사용을 부추긴듯했습니다. 하지만 많은 프로그래머들은 터보C를 사랑하며 아꼈습니다. DELPHI또한 그러했습니다. 요즘 대학에서는 MS-VISUAL-C를 가르키지만 보이지 않는곳에서는 DELPHI를 많이 선호하고 있습니다.
볼랜드사의 컴파일러는 프로그래머들이 프로그램 알고리즘에만 신경을 쓰고, 윈도우OS 제어 관련은 컴파일러가 해줘야 한다는 생각으로 컴파일러를 만들다보니 프로그래머가 신경쓸일이 많이 줄어 들게 됩니다.VISUAL-C는 그렇지 않습니다. 하나 하나 프로그래머가 핸들링해주어야 하므로 프로그램 기간이 오래 걸립니다. 하지만 VISUAL-C의 장점도 많이 있습니다.

얼마전에 출시된 DEPHI-PHP 또한 볼랜드의 아성을 잊지 않은 듯합니다. 한번 트라이얼버전 받아서 사용해보세요..
http://www.codegear.com
delphiforphp2screenshot.jpg

참 그리고 한글사용하시려면 아래 처럼 설정해야 합니다.
메뉴에서 /TOOL/OPTIONS 하신후 그림처럼 하세요.
1.jpg

2.jpg

Graphs on Flash - usingActionScript!

Posted on July 9, 2006. Filed under: ActionScript, Graphics |

Ads by Google
Complex Data to Visualize
Create Hierarchical Interactive Graphs. Free Structure101g Download
www.HeadwaySoftware.com



I have been reading up on ActionScript for a few days now. I started from the very basics, and decided that I would not directly dive into it without having any prior knowledge. Made a bit of progress. I wrote my first ActionScript program today. And it worked beautifully. This gives me a lot of ideas for future programs. Hopefully learning this will aid me in learning Javascript, as I think they are similar in many aspects.

I chose a 640×480 resolution for the movie. It’s a pretty simple program, and the one that I always try if I have the power of graphics. So far I have been able to work on graphics only in Turbo C++ with the graphics.h header file that comes along with it. But then ever since I shifted to standard C++, I have not had the opportunity to use graphics in any of my programs. This program is to draw the graph of any function. In this very basic code, the function has to be changed in the source code. Here’s my code:

var s:Number=48;
var i:Number=0;
var j:Number=0;
this.createEmptyMovieClip(”graph”, 1);
graph.lineStyle(1,0×000000,100);//(pixel width,colour,alpha)
do{
j=240-s*Math.sin((i-240)/s);
graph.moveTo(i,j);
i++;
j=240-s*Math.sin((i-240)/s);
graph.lineTo(i,j);
}while(i<640);

It basically draws the sine curve on screen. The createEmptyMovieClip command is required to create an object that will call the functions that are part the object of type MovieClip, like the ones that involves graphics. I don’t know what exactly the second parameter is supposed to do. It’s called “depth” and a value of 1 worked fine for me. I haven’t understood it’s exact purpose yet.

Here’s the output that I got for the above program:

sine.JPG

The lines are a little jagged due to resizing.

That made me real happy. At first, I didn’t get any output. But later I realised I need to call the lineStyle function to change the plot colour to black and to draw properly.

I decided to plot other functions as well, and the next one that came to my mind was the normal distribution curve. Here, I changed only one of the expressions in the code to the new formula - instead of both - by mistake. But the output was amusing:fusion.JPG

The region between the sine curve and the normal distribution curve is shaded. This is of course because the moveTo command moves the current position indicator to a point on one curve, and the lineTo draws a line from here to a point on the other curve. This gives a nice effect to the graph.
There was no stopping me now and I just kept trying out more functions one after the other. Here’s f(x)=exp(-x/3)*sin(3x) :

complicated.JPG

Since I found this simple enough, I decided to plot Mandelbrot’s set and was wondering if ActionScript could take that fairly higher amount of intensive calculations. But I was feeling really sleepy at around this time, and I don’t know if the program did not work because I was too sleepy to debug it properly or if Flash couldn’t handle it. I think it is the former :-) . I suppose I’ll tackle that some other day.

var s:Number=48;
var i:Number=0;
var j:Number=0;
this.createEmptyMovieClip("graph", 1);
graph.lineStyle(1,0x000000,100);//(pixel width,colour,alpha)
do{
j=240-s*Math.sin((i-240)/s)*Math.tan((i-240)/s);
graph.moveTo(i,j);
i++;
j=240-s*Math.sin((i-240)/s)*Math.tan((i-240)/s);
graph.lineTo(i,j);
}while(i<640);

Equation grapher
by ericlin

The source file include class files, so this is a Flash MX 2004 movie. Otherwise, it can be done by Flash MX.


Evaluate the equation object

I have discussed in previous session how to parse a string and get the value of an equation. At the end, I also discussed how to handle an equation string with variables. So, it is not difficult to get the value of "sin(x)" when we set x=0.3;

When we draw equation graph, we need to sample many x values and get the result of the equation before we plot those data out. We can accomplish this by repeated setting x and parsing the equation to get a new result.

However, to parse an equation string, we need to screen each character for existance of parenthesis and existance of any operator in the operatorSet array. It is time consuming.

Since what gets changed is the variable value only, the existence and position of the operators and parenthesis are the same as before , repeated parsing is not necessary. We can store down the operators and parenthesis. That is what my EquationObject class serves.

By this algorithm, to handle 100 sample x and get 100 y value is not a hard job any more. My evaluator does not evaluate the equation string. It evaluate the instance of EquationObject.

In this movie, about 400 x values are sampled. This is faster and more efficient.


The fit of Y range

Here is the scenario. We set x and y range from 0 to 8. We plot the equation "sin(x)". Well, half of the y points fall into the negative region. That means half of the curve is out of the lower bound of the canvas. Besides, the curve is located low and occupies only one-eighth of the canvas leaving a large blank area in the upper half. This is ugly and stupid.

To correct this, we need to calculate the Y range of the curve. We walk through each y value in the y Array and pick the maximal value and minimal value. Calculate the y range by yMax-yMin so that we can plot and fit our curve to the canvas.The highest point of the curve should fall on the top edge of the canvas and the lowest point of the curve should fall on the bottom edge of the canvas.

Unfortunately, the policy is not always possible. There are bugs. Lets try to remove the bug.

P.S. in my source file, if we set yMin, yMax then the automatic fit function is disabled. This is necessary in some condition, such as doing a comparison between two equations.


The infinity - range too big

Check this scenario. How to plot the equation "1/x" with x ranging from -1 to 1 ?

When x=0, the value is infinity. Even worse, when x is near the x, the value 1/x is very very large. If we accept that y value, then the y range is very large. The curve is very ugly.

Can you guess what it had looked like ? Well, the graph shows a max point at the upper edge and all other points fall at the lower edge of the canvas. Yes, since the y range is very large, all values are zoomed out as if those values are nearly 0 except the max point.

To correct this, I have to skip off those infinity values or values that are un-acceptably large compared with other values. The algorithm should not be too complex. Flash can easily hang out for complex algorithm.

I write a simple script. I calculate the slope of the curve. When the curve is curving upward or downward too sharply, I take that point as infinity and skip it off. Mathematically, this algorithm may not be so reasonable, but it does serve our goal.

So, if we plot the equation "1/x" from -1 to 1, we see the points near the x=0 zone are missing. 


The flat line - range too small

Scenario: How to plot the equation "sin(x)^2+cos(x)^2" with whatever x range ?

Well, for any x value, the result theoretically is always 1. So we expect to see a flat line on our canvas. No ?

My script would try to put the maximum value at the upper edge and minimum value at the lower edge of the canvas. If the "curve" is a flat horizontal line, how could it possibly do this ?

Can you guess how this equation had been plot ? Well, the result is a bizzare up and down spike.

Flash has limitation in calculation of float point. Besides, the sin and cos functions are just giving estimated values. In fact, when Flash calculate sin(x)^2+cos(x)^2, it gives a value "almost" 1 but not just 1. So, the result of the plot is still a curve with minute up and down not just a flat line. Since the difference between y max and y min is minute, the range is minute and the zoom-in effect is large. The end result is magnification of the up and down of the curve.

To correct this, we add some script to rule out such condition. When y range is too small, we add 5 as its maximum value and subtract 5 as its minimum value.


make the grid scales

Scenario: If I my bottom value is 10.1 and top value is 90, I want to draw grid lines at position where it represent 20- 40- 60- 80 - that counts 4 grid lines. If the top value is 55, I would draw grid lines at 20-30-40-50- total 4 lines. If the top value is 30, then I draw lines at 15 - 20 - 25 -30 total 4 lines.

Principle 1 : I want to keep the number of grid lines around 4 lines, 3 or 5 are acceptable.

Principle 2 : I want the grid line position "rounded" to 0 or 5 if possible. Positions such as 53- 76 -99 -122 should be avoid. In stead, I would hope it to be 50 - 75 -100 -125, although it may be one line more or less.

Well, it is more difficult than I had expected. So, I can not but use a brutal way.

First, I estimate what is the power of 10 for the space. Is it 0.01, or 0.1, or 1 or 10, or 100, or 1000 ? This is done through the log10. The script is like this : Math.floor(Math.log(dx)/Math.LN10);

For a result such as 10, then I test 2, 5, 10, 20, 50 and see how many lines I need to draw, if it counts less than 5, accept it.

If anyone knows a better way, please email me. I would appreciate sincerely.


Sampling limitation

Here is scenario: Plot a graph on to a canvas of 300-pixel-wide for equation "y=sin(x)", with x=-300 to 300.

The result is very ugly and useless because we plot it with in-adequate x sampling. Not every "peak" of the sin wave gets caught. So, not only the straight lines replace the curves, the repeated peaks in the graph do not sit at the same height as we expected.

Lets go back to that scenario. How about plot is with x range 0 to 8. The result is a beautiful curve. Is this beautiful sin wave plot accurate enough ? Here we see two peaks. Are they at the same height ? No. Not exactly.

The peak should occurr when x=(Math.PI)/2 , around half of 3.14159..... I dont think we pick that point exactly.

Theoretically, the peak when x=PI/2 should be at height of 1. No, in our graph, no single Y value is exactly 1.

How many sampling is "enough" ? I dont think there is an easy answer. 


The equation grapher


download source fla

ericlin@ms1.hinet.net

http://ericlin2.tripod.com/math2/graphQuizt.html

'Computer Science' 카테고리의 다른 글

TCP/IP 소켓 프로그래밍 with C#  (0) 2009.04.22
Delphi for php 사용안내  (0) 2009.04.22
contextmenustrip 메뉴에 하위메뉴 동적으로 생성  (0) 2009.04.15
Pixel Color Under Mouse  (0) 2009.04.09
[C#]마우스 좌표 얻기  (0) 2009.04.08
contextmenustrip 메뉴에 하위메뉴 동적으로 생성

ContextMenuStrip 메뉴의 특정항목의 하위 메뉴를 추가시키려고 합니다.

예를 들면 네이트온의 주소록 관리에서 주소록 리스트에서 오른쪽 마우스를 클릭하면 ContextMenu가 출력되고

여러 항목중 그룹이동 항목의 하위메뉴로 현재 생성되어 있는 그룹명이 출력됩니다.

이것과 같은 기능을 만드려고 하는데 ContextMenuStrip의 하위메뉴를 어떻게 생성해야 할지 잘 모르겠습니다.

또한 생성한 메뉴들에대해 이벤트처리도 해야하는데...

이것저것 해봐도 도무지... 답변좀 부탁드립니다.

이 글에 평점 주기:
[답변]..
메뉴로 들어갈 메뉴스트립 들입니다.

ContextMenuStrip popupViewToolbars;
ToolStripMenuItem popupViewToolbarsCanvasToolbox;
ToolStripMenuItem popupViewToolbarsStandard;
ToolStripMenuItem popupViewToolbarsStatus;

그리고, 이렇게 정의해 주면 됩니다.

//생성
popupViewToolbars = new ContextMenuStrip();
popupViewToolbarsStandard = new ToolStripMenuItem("Standard");
popupViewToolbarsCanvasToolbox = new ToolStripMenuItem("Canvas Toolbox");
popupViewToolbarsStatus = new ToolStripMenuItem("Status");
//하위메뉴로 추가하는 방법
popupViewToolbars.Items.AddRange(new ToolStripItem[] {
 popupViewToolbarsStandard,
 popupViewToolbarsCanvasToolbox,
 new ToolStripSeparator(),
 popupViewToolbarsStatus
});
//event
popupViewToolbars.Opened += new EventHandler(popupViewToolbars_Opened);
popupViewToolbarsStandard.Click += new EventHandler(popupViewToolbarsStandard_Click);
popupViewToolbarsCanvasToolbox.Click += new EventHandler(popupViewToolbarsCanvasToolbox_Click);
popupViewToolbarsStatus.Click += new EventHandler(popupViewToolbarsStatus_Click);

'Computer Science' 카테고리의 다른 글

Delphi for php 사용안내  (0) 2009.04.22
flash plot  (0) 2009.04.21
Pixel Color Under Mouse  (0) 2009.04.09
[C#]마우스 좌표 얻기  (0) 2009.04.08
EVC 4.0 프로그래밍의 준비  (0) 2009.04.06

http://support.microsoft.com/kb/892462

To Read This,

Microsoft Knowledge Base Article

This article contents is Microsoft Copyrighted material.
©2005-©2007 Microsoft Corporation. All rights reserved.Terms of Use | Trademarks




Article ID: 892462 - Last Review: May 31, 2007 - Revision: 1.5

How to use Visual C# to obtain the color of the pixel that is referenced by the mouse pointer

INTRODUCTION

This article describes how to use Microsoft Visual C# to obtain the color of the pixel that is referenced by the mouse pointer.

MORE INFORMATION

To obtain the color of the pixel that is referenced by the mouse pointer by using Visual C#, follow these steps:
  1. In Microsoft Visual Studio .NET 2003, create a new Visual C# Windows application.
  2. Add a Label control that is named label1 to capture the pixel color.
  3. Create a class that contains the Dlllmport statements that are required to call the Microsoft Windows GDI functions, and then capture an image that represents the current desktop.
  4. Associate the MouseDown event of the label with an event handler that is named label1_MouseDown.
  5. In the label1_MouseDown event handler, capture an image of the current desktop.
  6. Associate the MouseUp event of the label with an event handler that is named label1_MouseUp.
  7. In the label1_MouseUp event handler, retrieve the color that is associated with the current pixel location of the mouse pointer, and then set the BackColor of label1 to the color of the mouse pointer pixel.
The following steps are detailed steps to obtain the color of the pixel that is referenced by the mouse pointer:
  1. In Visual Studio .NET 2003, create a new Visual C# Windows application.
  2. Add one Windows Forms Label control to Form1.cs.
  3. Click the label1 control, and then change the Text property to an empty string.
  4. Change the BorderStyle property to FixedSingle.
  5. In the Solution Explorer, right-click Form1.cs, and then click View Code.
  6. Add the following Using statements to the top of the Form1.cs source code.
    using System.Runtime.InteropServices;
    Note This step adds the required references to call the InteropServices functions and methods.
  7. Add the following Bitmap variable to Form1.cs at the start of the Form1 class.
    private Bitmap myBitmap;
  8. Add the following Win32APICall class to Form1.cs after the Form1 class.

+ Recent posts